Application hanging on DialogResult.OK - c#

Im having some trouble my program hanging when selecting a file in a file dialog. This is the code that is showing the file browser dialog:
private void isForgeIncluded_btn_Click(object sender, EventArgs e)
{
this.isForgeIncluded.Text = FolderFileDialog("file", isForgeIncluded.Text, "Forge installer file (*.jar)|*.jar");
}
public string FolderFileDialog(string type, string current, string fileTypes = "All files (*.*)|*.*|All files (*.*)|*.*", string StartFolder = "C:\\")
string ReturnString = current;
if (current != "")
{
StartFolder = Path.GetFullPath(current);
}
if (type == "file")
{
OpenFileDialog minecraftFile = new OpenFileDialog();
minecraftFile.Title = "Select file";
minecraftFile.InitialDirectory = StartFolder;
minecraftFile.RestoreDirectory = true;
minecraftFile.Filter = fileTypes;
if (minecraftFile.ShowDialog() == DialogResult.OK)
{
ReturnString = minecraftFile.FileName;
return ReturnString;
}
minecraftFile = null;
}
return ReturnString;
}
I've narrowed the problem down to between the "if" statement and the "Return string = minecraftFile.FileName;" .. When using the debugger the program takes up to a five second break between those two lines. After its break it comes back and returns the value as if nothing was wrong. But IntelliTrace sometimes comes up with a "FileNotFound Exception" even though the program never shows me any error messages, and returns the correct value to the textbox as it should.
The wierd part is that it is not always this happens. Its random and can happen even though i select the same file as last time. The files i select are local files too on the system drive.
What could be wrong? Does the code look as it should?

Two basic problems can cause trouble with OpenFileDialog. First is misbehaving shell extension installed on your machine, they'll get loaded into your process when you open the dialog. A basic check is that you don't see trouble with Notepad's File + Open command and that you see nothing special in the Visual Studio Output window while the dialog is active. Enabling unmanaged debugging gives you more info.
The second cause is having an issue with the thread state of your UI thread. If must be initialized as a single-threaded apartment to be able to show this dialog properly. Go back to your Main() method, normally in Program.cs, and ensure it has the [STAThread] attribute.
If that doesn't pan out then we need more info about the code that's misbehaving. You need to enable unmanaged debugging, Project + Properties, Debug tab. And enable the Microsoft symbol server, Tools + Options, Debugging, Symbols. And disable Just My Code debugging, Tools + Options, Debugging, General. Hit Debug + Break All right after you get it to misbehave and post the content of the Call Stack window.

Related

C# - OpenFileDialog too slow only first time on pressing OK

I have a button which opens an OpenFileDialog. When I compile the application, run it for the first time, press the button, select file(s) and then press the accept dialog button, it waits for about a minute before adding the selected file(s) into my list box.
If I close the application, restart it and do the same thing as above, everything works fast and normal. From then on it always works fast. It's only the very first time I run it after the compilation when it's too slow.
The code extract is below. What could be wrong with the dialog? Why does it run slowly for the first time? Thank you.
void ButtonAddClick(object sender, EventArgs e)
{
this.openFileDialog.FileName = String.Empty;
this.openFileDialog.InitialDirectory = this.openPath;
if (this.openFileDialog.ShowDialog() == DialogResult.OK)
{
foreach (string file in this.openFileDialog.FileNames)
{
if (!File.Exists(file))
{
this.ShowStatus("Error occured selecting file " + Path.GetFileName(file));
}
else if (!this.listBoxFiles.Items.Contains(file))
{
this.listBoxFiles.Items.Insert(0, file);
}
else{
this.ShowStatus("File " + Path.GetFileName(file) + " already selected");
}
}
}
if (this.listBoxFiles.Items.Count > 0)
{
this.openPath = Path.GetDirectoryName(this.listBoxFiles.Items[0].ToString());
this.listBoxFiles.Enabled = true;
this.buttonClear.Enabled = true;
this.buttonFolder.Enabled = true;
}
}
If you are facing this problem of slowness at first initialisation, my suggestion is listed below to rectify this.
For VS debugging, in Visual Studio IDE, just go to Tools>Options>Debugging. Find settings page named [Symbols]. Click it to load the page content. On the right side panel if “Microsoft Symbol Servers” checkbox is checked, just uncheck it and press “Ok” to save the settings. Now on running compiled exe, if the problem still persists then I suggest to perform some cleanup operation on your pc. Also make sure that all timely VS updates are incorporated in your VS. Let me know if this helps if not we can figure out something else.
Try calling Directory.GetFiles(folderPath); prior to showing the OpenFileDialog window. That might trigger the same caching that's occurring after you do OpenFileDialog the first time with your current method.

How can I display a FolderBrowserDialog in LINQPad?

I want to browse for a folder in a LINQPad script so I tried using FolderBrowserDialog. It didn't work.
Here is a snippet showing what I'm doing?
string path = "";
var browser = new FolderBrowserDialog { ShowNewFolderButton = false };
if (browser.ShowDialog() == DialogResult.OK)
{
path = browser.SelectedPath;
}
This runs and hangs on the line with ShowDialog() with the yellow execution pointer against that line, but the folder browser dialog isn't visible.
I know that there is an overload for ShowDialog() that takes an IWin32Window owner argument and thought that might be the solution, but haven't yet figured out how to get an IWin32Window for the main LINQPad window. I hoped the Util class might provide a way but unless I'm missing it, it doesn't seem to.
Anyone have advice on getting around this problem?
Not solution, but an alternative, the FilePicker controle (part of new LinqPad Input Controls).
you can write:
new FilePicker().Dump().TextInput += (x, e) => ((FilePicker)x).Text.Dump();
or:
var picker = new FilePicker();
picker.TextInput += (x, e) => {
var fileName = picker.Text;
//action with the file...
};
full example:
void Main()
{
new FilePicker().Dump().TextInput += (x, e) => procces(((FilePicker)x).Text);
}
void procces(string file)
{
file.Dump("chosen file...");
//...
}
Setting the Run each query in its own process option to true is the cause of the problem. Setting that option back to the default false allows the code described above to run as expected.
However, making this change disables the built-in debugging. Furthermore the behaviour is still slightly problematic.
On first running the script the dialog is displayed and the script runs to completion after Ok or Cancel is selected. However, on running the script a second time it hangs as described in the question. After cancelling the execution and running it again the dialog displays but on the time after that it hangs again, and so on.
It was pointed out that setting the Always use fresh application domains option may resolve this and it does, allowing the dialog to display on every execution of the script.
I just came across this problem with LINQPad 5. I needed a folder picker similar to the file picker. Your solution worked without me having to modify LINQPad5 settings. The problem was the dialog was staying in the background. So here's how I got your snippet to work with that dialog in focus. Instead of using the FolderBrowseDialog.ShowDialog() I used the overload that passes in a windows form. I created a new form with description and window position then passed that to ShowDialog. That allowed me to set the description and window positioning.
string path = "";
using ( var browser = new System.Windows.Forms.FolderBrowserDialog { ShowNewFolderButton = false })
{
browser.Description = "Select Folder For Foo Processing";
var form = new System.Windows.Forms.Form(){TopMost = true, TopLevel = true};
var result = browser.ShowDialog(form);
if (result == System.Windows.Forms.DialogResult.OK)
{
path = browser.SelectedPath;
}
}
path.Dump();
I tried to initialize the form in ShowDialog with the settings, but had problems so I opted to declare it before show dialog. Hope this helps anyone with this problem.

How can I read the command line supplied to an offline clickonce application?

I have a simple application that opens a TCP connection and communicates via Telnet to another system. The application is to read a file that contains parameters and a simple scripting language to issue commands based on prompts from the connection.
Written in VS2013 using .NET 4
My application works as designed with one little exception.
I am publishing to a location using VS2013 which works well enough but the idea is to read a command line passed to my application that contains the path/file for the script to execute and that doesn't work as expected.
Finding out the hard way, the standard args[] parameters are not passed when it's published this way.
I have searched out multiple solutions that don't work both on here and other sites.
This is the basis (excerpt from page) of my current implementation to read the command line (found here: http://developingfor.net/2010/06/23/processing-command-line-arguments-in-an-offline-clickonce-application/). This seems to be similar to all solutions I've found, each with some variation that doesn't work.
string[] args = null;
if (ApplicationDeployment.IsNetworkDeployed)
{
var inputArgs = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData;
if (inputArgs != null && inputArgs.Length > 0)
{
args = inputArgs[0].Split(new char[] { ',' });
}
}
else
{
args = e.Args;
}
This SHOULD return args[] with parameters passed. I believe it would also include the actual command with path to the application. The Split function is because the author wishes to pass arguments separated by commas and not spaces.
My incarnation of this is a bit longer to include some checks to see if we actually get arguments from being compiled as an exe instead. If I compile to EXE and supply a command line, all is fine. Here is my code, not very concise as I've made lots of changes to debug and make this work.
I haven't figured out how to debug in the ide as network deployed with a command line so my debug code is via messagebox.
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length == 0) //If we don't have args, assume onclick launch
{
if (ApplicationDeployment.IsNetworkDeployed) //are we oneclick launched?
{
var cmdline = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData; //this should hold the command line and arguments????
if (cmdline != null && cmdline.Length > 0) //we have something and it contains at least 1 value
{
//This is all debug code to see what we get since we can't trace in this mode
MessageBox.Show(cmdline.Length.ToString()); //how many objects do we have?
foreach (String s in cmdline)
{
MessageBox.Show(s); //show us the value of each object
}
Application.Run(new frmMain(args)); //launch the form with our arguments
}
else
{
//quit application
MessageBox.Show("No command line.1"); //debug so we know where we failed
Application.Exit();
}
}
else
{
//quit application
MessageBox.Show("No command line.2"); //debug so we know where we failed
Application.Exit();
}
}
else
{
Application.Run(new frmMain(args)); //launch form with args passed with exe command line
}
}
Running the code above like this:
sTelent.application 1234
I have also explored the URL passing method which seems to only apply if launched from a web server, which this application is not.
At first I got NULL for my object:
AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData
After more research I discovered that in my project properties under the Publish section there is an option button and under Manifests I can choose "Allow URL Parameters to be passed to application"
I checked this box and while I get different behavior, I don't get the desired behavior.
With that option checked I now get 2 messages boxes: The first showing the number of objects in cmdline and that number is 1 and the second showing the value of that one object which contains only the path/command to my application. No other objects and definitely not my arguments.
Am I totally off base? How do I get my command line arguments from an offline clickonce published application?
It seems that you must put the argument on the .appref-ms and not on not the .application or .exe for this to work correctly for clickonce based applications.
I created a short cut on my desktop by copying the installed application link found under All Programs. That should create an icon on your desktop with the same name as your application.
Then, open a command prompt, type in “%userprofile%\Desktop\My App Name.appref-ms” word for word (of course replace "my app name" with your application name). It should then pass the arguments. You can also put the command within a .bat file. I'm sure that you can also reference the link directly, it typically is located under c:\users[user profile]\appdata\roaming\Microsoft\windows\start menu\programs[app name]

How to open a .DWG file in Autocad 2014 through C#

Hi I have a requirement in which I have to open a drawing file stored in C:\Temp Folder.
I tried the following code
public void launchacad(string pth) //pth is the path to the .DWG file
{
const string progID = "AutoCAD.Application.19.1";
const string exePath = #"C:\Program Files\Autodesk\AutoCAD 2014\acad.exe";
AcadApplication acApp = null;
try
{
acApp =
(AcadApplication)Marshal.GetActiveObject(progID);
}
catch { }
if (acApp != null)
{
MessageBox.Show("An instance of AutoCAD is already running.");
}
else
{
try
{
ProcessStartInfo psi =new ProcessStartInfo(exePath);
psi.WorkingDirectory = #"C:\Temp";
psi.Arguments = pth;
Process pr = Process.Start(psi);
pr.WaitForInputIdle();
while (acApp == null)
{
try
{
acApp =(AcadApplication)Marshal.GetActiveObject(progID);
}
catch
{
Application.DoEvents();
}
}
}
catch (Exception ex)
{
MessageBox.Show(
"Cannot create or attach to AutoCAD object: "
+ ex.Message
);
}
}
if (acApp != null)
{
acApp.Visible = true;
acApp.ActiveDocument.SendCommand("_MYCOMMAND ");
}
}
But as soon as Autocad starts it popups an error message saying Cannot find the specified drawing. When I use CMD.exe and type
"C:\Program Files\Autodesk\AutoCAD 2014\acad.exe" "C:\Temp\41 Stabd.dwg" It opens Autocad with the file(41 Stand.dwg) open.
I can't understand where I am making an error. Can someone help me out.
If still the drawing persists with problems, continue on to the next set of steps.
These can be done in any order, but have been listed in the order that Autodesk recommends makes the most sense. The file can be checked after each step. If things appear back to normal, there is no need to continue on to the rest of the steps.
​Open a blank DWG and type RECOVER at the command line. Browse to the problematic file to - allow AutoCAD a chance to restore the file.
Type OVERKILL at the command line, and select all objects. Check or uncheck properties to include or ignore, then click OK.
Type DELCON at the command line, and select all objects.
Type BREP and select all objects (if there are solids or surfaces in the file)
Type -SCALELISTEDIT, then "R" for reset, then "Y" for yes.
Type FILTERS, then click on the 'delete filters' button.
The DGNPURGE tool can be run if the file size is unexpectedly very large: http://knowledge.autodesk.com/article/AutoCAD-DWG-files-unexpectedly-increase-in-file-size
Try using a different version of AutoCAD to open the drawing, such as AutoCAD 2013 vs. AutoCAD 2015 or plain AutoCAD vs. AutoCAD Architecture, etc. Try different computers if available.
Open a blank DWG, and try to attach the problematic file as an XREF. If it allows you to attach the file, try next to BIND it to the current file. If that works, run the repair steps listed above.
Use the SAVEAS command to save the DWG in an older file format. Attempt to open the newly created file.
Export the file to DXF format using the DXFOUT command. Next, open a blan DWG and use the DXFIN command to import the file just created.
< Restore the Layout tabs:
Right-Click one of the default layout tabs
Select 'From Template...'
Open the original file
Choose the layout tabs to restore. (It is recommended to do this one tab at a time, in case one or more layout tabs are corrupted)
Move drawing objects between model and paper space. You may find that only one drawing space is usable in your file, although your main concern is model space:
​​1. Create a new layout and if need be, create a viewport.
Use CHSPACE to move all the geometry to paper space.
Create a new drawing and use the Design Center (ADC) to move the layout from the damaged file into it.
Use CHSPACE again to move the geometry back to model space.
Restore the original layouts from the bad file using the Design Center.
Dissect the drawing. In a copy of the file, conduct a process of elimination using QSELECT to select different object types and then delete them to see if that fixes what is wrong in the file. Do PURGE All after each deletion. Eventually you should remove the problem elements and then you can choose to leave them out, copy them in again from another file, recreate them, or further troubleshoot individual items to pinpoint exactly which one is problematic. A quick start to this whole process is to delete everything in the drawing and then test it. This will quickly tell you if the issue is with a drawing object or if it is a part of the drawing database.​

Invoking standard "File changed outside Visual Studio" dialog

I have succesfuly created custom single view editor in my VSPackage. One of many things I had to cope with was reacting to situation when edited file was changed outside Visual Studio - "standard" editors in Visual Studio display dialog with options like "yes", "yes to all" (reload content) etc., so if more files had changed, only one dialog is displayed.
However, the only thing I can do in my VSPackage so far is display custom dialog when the file had changed. It is not pretty - when file edited in my editor changed along with some others, there will be two completely different dialogs displayed to the user.
So the question is - is there any way how to invoke "standard" Visual Studio "file changed outside VS" dialog for my file?
Sounds like you are using the IVSFileChangeEx interface.
This blog post might be almost what you're looking for. Normally this is used for checking to see if a file can be edited, or reloaded and will provide a file dialog prompt to (check-out or reload).
This uses the IVsQueryEditQuerySave2 interface. You probably want to call DeclareReloadableFile, which will "States that a file will be reloaded if it changes on disk."
private bool CanEditFile()
{
// --- Check the status of the recursion guard
if (_GettingCheckoutStatus) return false;
try
{
_GettingCheckoutStatus = true;
IVsQueryEditQuerySave2 queryEditQuerySave =
(IVsQueryEditQuerySave2)GetService(typeof(SVsQueryEditQuerySave));
// ---Now call the QueryEdit method to find the edit status of this file
string[] documents = { _FileName };
uint result;
uint outFlags;
int hr = queryEditQuerySave.QueryEditFiles(
0, // Flags
1, // Number of elements in the array
documents, // Files to edit
null, // Input flags
null, // Input array of VSQEQS_FILE_ATTRIBUTE_DATA
out result, // result of the checkout
out outFlags // Additional flags
);
if (ErrorHandler.Succeeded(hr) && (result ==
(uint)tagVSQueryEditResult.QER_EditOK))
{
return true;
}
}
finally
{
_GettingCheckoutStatus = false;
}
return false;
}

Categories