c# AutoUpdater.NET - Application should not close, if update available - c#

I'm using AutoUpdater.NET for updating my applications. It's a great library. My program collects data for inventory system-data, sent it to database and than close the application.
this.Close();
The problem is, that the program also close, if an update is available. I want, that the application stay open, until the user update or cancel. I know that I have to check, if update is available or update-form is open, but I don't know how. Could someone please help? (Sorry, I'm beginner)
AutoUpdater.Start(updatePath);
AutoUpdater.ShowSkipButton = false;
AutoUpdater.ShowRemindLaterButton = false;
AutoUpdater.Mandatory = true;
//AutoUpdater.UpdateMode = Mode.Forced;
AutoUpdater.RunUpdateAsAdmin = false;
var currentDirectory = new DirectoryInfo(Environment.CurrentDirectory);
if (currentDirectory.Parent != null)
{
AutoUpdater.InstallationPath = currentDirectory.FullName;
}

The solution (in my case) was to replace Environment.CurrentDirectory with Application.StartupPath

Related

Prevent file association from opening the app again

I develop a wpf app and i associated a file type named .fcsc. The application opens when the file is doubled clicked but it execute a new instance of the app. What i want is that if the app is already running, open the file in that instance not in a new one.
How can i archive that?
This is what i have when a file is open:
if (AppDomain.CurrentDomain.SetupInformation != null
&& AppDomain.CurrentDomain.SetupInformation.ActivationArguments != null
&& AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData != null &&
AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData.Any())
{
// is a file association invoke, open the window
InstallPluginWindow installPluginWindows = new InstallPluginWindow(AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData);
installPluginWindows.Show();
installPluginWindows.Owner = this;
this.Opacity = 0.5;
this.IsEnabled = false;
installPluginWindows.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
installPluginWindows.Closed += installPluginWindows_Closed;
}
else
{
NegotiateLogin();
}
The easy part is setting up a mutex to check for another instance. In your app main or startup code you waould need to so something like the code below:
bool exclusive;
System.Threading.Mutex appMutex = new System.Threading.Mutex(true, "MyAppName", out exclusive);
if (!exclusive)
{
//Another instance running
} ...
GC.KeepAlive(appMutex);
Next, you need to implement a way to message the first application instance and pass in the filename that was double clicked. You can do this in many ways, however, sending a custom message to the main window seems to be the most straightforward. Here is an alternative to message another application.

Stop process if webBrowser control hangs

I am using the WebBrowser control.
This works fine most of the time however wehn navigating to a new page or waiting for a new page to load can sometimes hangs.
Is there a way to catch this? i.e. if the page is failing to navigate or load after a certain amount of time then kill the process?
I am using the - webBrowser1_DocumentCompleted event to pick up ertain behaviours when the page loads/navigates as expected however not sure how to catch if a page is hanging??
Maby you should try to implement some kind of timeout logic? There are quite many samples in web about this. F.e. this one
Also you might be interested in this event of WebBrowserControl ProgressChanged
This is due to that webbrowser component is very basic model of internet explorer, and it get stuck at ajax pages. You can fix this problem explicitly to use latest version of internet explorer... Using this code...
try
{
string installkey = #"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION";
string entryLabel = "YourExe.exe";
string develop = "YourExe.vshost.exe";//This is for Visual Studio Debugging...
System.OperatingSystem osInfo = System.Environment.OSVersion;
string version = osInfo.Version.Major.ToString() + '.' + osInfo.Version.Minor.ToString();
uint editFlag = (uint)((version == "6.2") ? 0x2710 : 0x2328); // 6.2 = Windows 8 and therefore IE10
Microsoft.Win32.RegistryKey existingSubKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(installkey, false); // readonly key
if (existingSubKey.GetValue(entryLabel) == null)
{
existingSubKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(installkey, true); // writable key
existingSubKey.SetValue(entryLabel, unchecked((int)editFlag), Microsoft.Win32.RegistryValueKind.DWord);
}
if (existingSubKey.GetValue(develop) == null)
{
existingSubKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(installkey, true); // writable key
existingSubKey.SetValue(develop, unchecked((int)editFlag), Microsoft.Win32.RegistryValueKind.DWord);
}
}
catch
{
MessageBox.Show("You Don't Have Admin Previlege to Overwrite System Settings");
}
}
Right Click Both your Exe. And vshost.exe and Run as Administrator To Update Registry for this Application....

How to close a file in Autocad using C# keeping acad.exe running?

I am using visual studio 2010 and I am having a .DWG file which I want to open in autocad. Till now I have used this.
Process p = new Process();
ProcessStartInfo s = new ProcessStartInfo("D:/Test File/" + fileName);
p.StartInfo = s;
p.Start();
But what I want is to close the file inside the Autocad but not the autocad itself. (Means atocad.exe should be kept running).
Till now I hve used this but its closing the acad.exe not the file.
foreach (Process Proc in Process.GetProcesses())
{
if (Proc.ProcessName.Equals("acad"))
{
Proc.CloseMainWindow();
Proc.Kill();
}
}
Take the Autocad .NET libraries from Autodesk Sites (http://usa.autodesk.com/adsk/servlet/index?id=773204&siteID=123112)
Then you will be able to use Application and Document classes.
They will give you full control over opening and closing documents within the application.
You can find many articles on that, and can ask further questions.
AutoCAD does have an api. there are 4 assemblys. Two for in-process and two for COM.
inprocess :
acdbmgd.dll
acmgd.dll
COMInterop :
Autodesk.Autocad.Interop.dll
Autodesk.Autocad.Interop.Common.dll
this is a method that will open a new instance of AutoCAD or it will connect to an existing running instance of AutoCAD.
you will need to load these .dlls into your project references.
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
namespace YourNameSpace {
public class YourClass {
AcadApplication AcApp;
private const string progID = "AutoCAD.Application.18.2";// this is AutoCAD 2012 program id
private string profileName = "<<Unnamed Profile>>";
private const string acadPath = #"C:\Program Files\Autodesk\AutoCAD 2012 - English\acad.exe";
public void GetAcApp()
{
try
{
AcApp = (AcadApplication)Marshal.GetActiveObject(progID);
} catch {
try {
var acadProcess = new Process();
acadProcess.StartInfo.Arguments = string.Format("/nologo /p \"{0}\"", profileName);
acadProcess.StartInfo.FileName = (#acadPath);
acadProcess.Start();
while(AcApp == null)
{
try { AcApp = (AcadApplication)Marshal.GetActiveObject(progID); }
catch { }
}
} catch(COMException) {
MessageBox.Show(String.Format("Cannot create object of type \"{0}\"",progID));
}
}
try {
int i = 0;
var appState = AcApp.GetAcadState();
while (!appState.IsQuiescent)
{
if(i == 120)
{
Application.Exit();
}
// Wait .25s
Thread.Sleep(250);
i++;
}
if(AcApp != null){
// set visibility
AcApp.Visible = true;
}
} catch (COMException err) {
if(err.ErrorCode.ToString() == "-2147417846"){
Thread.Sleep(5000);
}
}
}
}
}
closeing it is as simple as
Application.Exit();
and forgive the code. its atrocious, this was one of my first methods when i just started developing...
I doubt you will be able to do this unless AutoCAD has an API that you can hook into and ask it to close the file for you.
Your c# app can only do things to the process (acad.exe) , it doesn't have access to the internal operations of that process.
Also, you shouldn't use Kill unless the process has become unresponsive and certainly not immediately after CloseMainWindow.
CloseMainWindow is the polite way to ask an application to close itself. Kill is like pulling the power lead from the socket. You aren't giving it the chance to clean up after itself and exit cleanly.
There is one other possibility - this will only work if your C# code is running on the same machine as the AutoCAD process and it is not really recommended, but, if you are really stuck and are prepared to put up with the hassle of window switching you can send key strokes to an application using the SendKeys command.
MSDN articles here:
http://msdn.microsoft.com/EN-US/library/ms171548(v=VS.110,d=hv.2).aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx
Using this you could send the key strokes to simulate the user using the menu commands to close the file.
To perform the closing of file, best way out is to follow the steps at this ObjectARX SDK for c# and change the following code with the below code.
[CommandMethod("CD", CommandFlags.Session)]
static public void CloseDocuments()
{
DocumentCollection docs = Application.DocumentManager;
foreach (Document doc in docs)
{
// First cancel any running command
if (doc.CommandInProgress != "" &&
doc.CommandInProgress != "CD")
{
AcadDocument oDoc =
(AcadDocument)doc.AcadDocument;
oDoc.SendCommand("\x03\x03");
}
if (doc.IsReadOnly)
{
doc.CloseAndDiscard();
}
else
{
// Activate the document, so we can check DBMOD
if (docs.MdiActiveDocument != doc)
{
docs.MdiActiveDocument = doc;
}
int isModified =
System.Convert.ToInt32(
Application.GetSystemVariable("DBMOD")
);
// No need to save if not modified
if (isModified == 0)
{
doc.CloseAndDiscard();
}
else
{
// This may create documents in strange places
doc.CloseAndSave(doc.Name);
}
}
}

Duplicate process (strange issue)

I am trying to prevent opening help file more than once.
This is the method I am using:
public void openHelp()
{
int count = 0;
string helpPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + #"\MyApp\Help\eHelp.chm";
System.Diagnostics.Process[] helpProcs = System.Diagnostics.Process.GetProcesses();
foreach (System.Diagnostics.Process proc in helpProcs)
{
if (proc.MainWindowTitle == "Sample App Help")
{
count++;
}
}
if (count == 0)
{
System.Diagnostics.Process.Start(helpPath);
}
else
{
}
}
The idea is, if you find the process with the same MainWindowTitle, then do not start a new one.
However, this is not reliable. In some cases it still starts the process, even though one is already running. Is there an issue with a logic?
Thank you.
P.S. Of course the MainWindowTitle is "Sample App Help", at least that is what I see while debugging.
Update:
Issue only occurs when user has minimised help file. So I suspect something happens in the system and I need to check something. Any suggestions?
The Remarks section in Process.MainWindowTitle contains the following note:
The main window is the window that currently has the focus; note that
this might not be the primary window for the process. You must use the
Refresh method to refresh the Process object to get the current main
window handle if it has changed.
Could this perhaps be the cause of your problem?
What about keeping the process id of a newly started help viewer and before starting another one, just check if the old one is still alive.
int id = ...
try
{
var proc = Process.GetProcessById(id);
}
catch
{
// no process running with that id
}

Can I use SetErrorMode in C# process?

I'm preparing for writing an online judge core,
A program that can compile user's code and run the program to check the answer like uva online judge.
And I'm having problem in catching the exception of submit program like below.
int main()
{
while(~scanf("%d %d",n,&m))
{
printf("%d\n",n+m);
}
return 0;
}
it's access denied at first line because it scan an integer to error position.
how can I catch runtime error for my process?
I used to use "try catch" to catch the exception,
but it didn't reply anything about runtime error.
so I only check the exit code of the submit program although it's not a good method to check except for a process..
and it shows like photo
I have to close the error message box manually,
and I find a solution that is to use a SEH Handler DLL for the process.
SetErrorMode(SEM_NOGPFAULTERRORBOX);
but I don't know how to use it in C# process.
and below is my code of judger
timer = new Stopwatch();
timer.Reset();
submitProg = new Process();
submitProg.StartInfo.FileName = outputFile;
submitProg.StartInfo.UseShellExecute = false;
submitProg.StartInfo.CreateNoWindow = true;
submitProg.StartInfo.RedirectStandardInput = true;
submitProg.StartInfo.RedirectStandardOutput = true;
submitProg.StartInfo.RedirectStandardError = true;
submitProg.StartInfo.ErrorDialog = false;
submitProg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
submitProg.EnableRaisingEvents = true;
submitProg.Start();
timer.Start();
progInput = submitProg.StandardInput;
progOutput = submitProg.StandardOutput;
progInput.Write(inputStream.ReadToEnd());
submitProg.StandardInput.Close();
while (!submitProg.HasExited)
{
peakPagedMem = submitProg.PeakPagedMemorySize64;
peakVirtualMem = submitProg.PeakVirtualMemorySize64;
peakWorkingSet = submitProg.PeakWorkingSet64;
if (peakPagedMem > memLimit)
{
submitProg.Kill();
}
if (timer.ElapsedMilliseconds > timeLimit)
{
timeLimitExceed = true;
submitProg.Kill();
}
}
timeUsed = timer.ElapsedMilliseconds;
timer.Stop();
if(submitProg.ExitCode!=0)systemRuntimeError = true;
Thanks for helping, and so sorry for my poor English.
==================================
p.s.
the question is how can I set error mode for the child process in C#.
My English is not good enough to explain the problem, so sorry.<(_ _)>
If you mean the Win32 API function SetErrorMode then you'll need to use P/Invoke, which is easy with such a simple signature:
[DllImport("kernel32.dll")]
static extern ErrorModes SetErrorMode(ErrorModes uMode);
[Flags]
public enum ErrorModes : uint {
SYSTEM_DEFAULT = 0x0,
SEM_FAILCRITICALERRORS = 0x0001,
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
SEM_NOGPFAULTERRORBOX = 0x0002,
SEM_NOOPENFILEERRORBOX = 0x8000
}
(The Site http://www.pinvoike.net/ is always a good place to start to get the right declaration.)
You cannot set the error mode in another process without injecting code into that process. Which is impossible to do easily in C#. It isn't going to work well in C/C++ either, these kind of programs don't live long enough to give you time to inject.
It doesn't solve your problem anyway, you also have to protect against programs that never exit after they got stuck in an endless loop. The simple solution is to give every program a limited amount of time to execute. Say 10 seconds. If it doesn't complete then Process.Kill() it and declare a failure. This will also take care of the programs that bomb with a message box.
Trivial to implement with the Process.WaitForExit(milliseconds) overload.

Categories

Resources