I'm creating an installer through Microsoft Visual Studio and my program needs a WAMP server to be running in the background to function properly.
Within the installer it installs WAMP to the folder of where the program has been installed and is running from, but how can I find where this actually is using c# code? Is there a way?
I tried this, but no luck;
try
{
Process.Start(#"[ProgramFilesFolder]Hex Technologies\32bit\wampmanager.exe");
checkStatus();
}
catch (Win32Exception exception)
{
MessageBox.Show(exception.Data.ToString());
}
You can try someting like
String EnviromentPath = System.Environment.GetEnvironmentVariable("ProgramFiles", EnvironmentVariableTarget.Machine);
but you may need to take care for x64 vs x32
Related
For the project I am working on, I am not allowed to use ClickOnce. My boss wants the program to look "real" (with an installer, etc).
I have installed Visual Studio 2012 Professional, and have been playing around with the InstallShield installer, and it definitely makes nice installers, but I can't figure out how to enable the application to "auto-update" (that is, when it starts up, checks to make sure that it is using the latest version).
I have been asked to make a tiny change to the code - switching an addition to a subtraction, and I don't really want people to have to uninstall the old version, and then have to reinstall the new version every time I make a small change like this.
How can I make the application check for updates, and install them? Or is this not possible (or not easy)?
There are a lot of questions already about this, so I will refer you to those.
One thing you want to make sure to prevent the need for uninstallation, is that you use the same upgrade code on every release, but change the product code. These values are located in the Installshield project properties.
Some references:
Auto update .NET applications
Auto-update library for .NET?
Auto update for WinForms application
Suggest a method for auto-updating my C# program
Automatic update a Windows application
I think you should check the following project at codeplex.com
http://autoupdater.codeplex.com/
This sample application is developed in C# as a library with the project name “AutoUpdater”. The DLL “AutoUpdater” can be used in a C# Windows application(WinForm and WPF).
There are certain features about the AutoUpdater:
Easy to implement and use.
Application automatic re-run after checking update.
Update process transparent to the user.
To avoid blocking the main thread using multi-threaded download.
Ability to upgrade the system and also the auto update program.
A code that doesn't need change when used by different systems and
could be compiled in a library.
Easy for user to download the update files.
How to use?
In the program that you want to be auto updateable, you just need to call the AutoUpdate function in the Main procedure. The AutoUpdate function will check the version with the one read from a file located in a Web Site/FTP. If the program version is lower than the one read the program downloads the auto update program and launches it and the function returns True, which means that an auto update will run and the current program should be closed. The auto update program receives several parameters from the program to be updated and performs the auto update necessary and after that launches the updated system.
#region check and download new version program
bool bSuccess = false;
IAutoUpdater autoUpdater = new AutoUpdater();
try
{
autoUpdater.Update();
bSuccess = true;
}
catch (WebException exp)
{
MessageBox.Show("Can not find the specified resource");
}
catch (XmlException exp)
{
MessageBox.Show("Download the upgrade file error");
}
catch (NotSupportedException exp)
{
MessageBox.Show("Upgrade address configuration error");
}
catch (ArgumentException exp)
{
MessageBox.Show("Download the upgrade file error");
}
catch (Exception exp)
{
MessageBox.Show("An error occurred during the upgrade process");
}
finally
{
if (bSuccess == false)
{
try
{
autoUpdater.RollBack();
}
catch (Exception)
{
//Log the message to your file or database
}
}
}
#endregion
The most common way would be to put a simple text file (XML/JSON would be better) on your webserver with the last build version. The application will then download this file, check the version and start the updater. A typical file would look like this:
Application Update File (A unique string that will let your application recognize the file type)
version: 1.0.0 (Latest Assembly Version)
download: http://yourserver.com/... (A link to the download version)
redirect: http://yournewserver.com/... (I used this field in case of a change in the server address.)
This would let the client know that they need to be looking at a new address.
You can also add other important details.
A Lay men's way is
on Main() rename the executing assembly file .exe to some thing else
check date and time of created.
and the updated file date time and copy to the application folder.
//Rename he executing file
System.IO.FileInfo file = new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location);
System.IO.File.Move(file.FullName, file.DirectoryName + "\\" + file.Name.Replace(file.Extension,"") + "-1" + file.Extension);
then do the logic check and copy the new file to executing folder
This is the code to update the file but not to install
This program is made through dos for copying files to the latest date and run your program automatically. may help you
open notepad and save file below with ext .bat
xcopy \\IP address\folder_share_name\*.* /s /y /d /q
start "label" /b "youraplicationname.exe"
These days you could use included in Windows 10 mechanism for app delivery called AppInstaller by packaging your app in MSIX bundle or package.
With it, you don't have to think about an installer (if your app doesn't use a lot of dependencies), background updating, and all of that. It's much better than ClickOnce, command-line usage works like a charm thanks to aliases, updates are non-obtrusive and could be used for background apps too.
The installation experience is much better too: a user just needs to click a button on HTML and Windows will install the app automatically.
It's not super-simple, I'd say more complicated than ClickOnce, but not as hard as Wix.
Official guide doesn't work with .NET Core or .NET 5 apps, so you can refer to this article, or to this great video, for example. This site also contains a lot of useful information.
I have an application with Crystal Reports in it. It has issues where it doesn't run on some computers. I haven't had this issue in a while so i tried to install all i remembered i needed.
First i made a simple console application that has an empty Crystal Report and all it does is instantiate the report and export to PDF right beside the EXE. Like that it's much faster to test. I put a try catch and wrote to a text file the stack trace of the error so i can debug quickly.
Ran it on my computer it works fine. Copied it onto a computer that it didn't work and tried it and it failed finding resources. So i installed the latest Crystal Runtime i need which is 13_0_22 64 bits.
Ran it again got the error :
Method not found:
'CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag
CrystalDecisions.ReportAppServer.ReportDefModel.ISCRExportOptions.get_ExportOptionsEx()'
Then i remembered that Crystal Report cannot run on Any CPU and that you have to specify one platform. Recompiled my Console project as x64 and now i am stuck with the following error :
The document has not been opened. at
CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocumentClass.set_ReportAppServer(String
pbsVal)
Now I made sure the computer has .net 3.5, .net 4.7 and Microsoft Visual C++ 2012 (as i know it's a requirement for Crystal).
Anything else i could be missing that i need to install ?
I already reinstalled the Crystal runtimes thinking it might be it but it's still not working.
Here's the code i use in case someone doesn't know what i mean by simple crystal report code :
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using System;
using System.Data;
using System.Diagnostics;
using System.IO;
namespace ConsoleApplication1678
{
class Program
{
static void Main(string[] args)
{
try
{
var report = new CrystalReport1();
if (File.Exists("rpt.pdf"))
{
File.Delete("rpt.pdf");
}
report.ExportToDisk(ExportFormatType.PortableDocFormat, "rpt.pdf");
Process.Start("rpt.pdf");
}
catch (Exception ex)
{
var error = ex.Message + "\n\n" + ex.StackTrace;
File.WriteAllText("error.txt", error);
}
}
}
}
Got my answer from SAP directly. Short version i need to use the latest version and tell all my clients to give me the list of all software they use that uses crystal so i can call these company and make them upgrade to the newest version because you cannot have 2 versions installed at the same time and they all need to be the same Bit format.
My application MUST run 64 bits as we use in excess of 20 gb of ram so i need to call all other application vendor to make their application 64 bits compiled version as by installing the latest makes all their program failed.
First of all I want to apologise if this question was answered before, I've searched but I didn't find anything [maybe didn't searched correctly]
I've developed a very simple console application, which doesn't do anything else but display a random number from 2 integers.
Code:
int miNumber;
int mNumber;
bool ok = false;
try
{
miNumber = Convert.ToInt32(minNumber);
mNumber = Convert.ToInt32(maxNumber);
ok = true;
}
catch (Exception)
{
Console.WriteLine("Only digits allowed!");
Console.ReadKey();
ok = false;
}
if(ok)
{
// Generate
var x = new Random();
Console.WriteLine(string.Format("Generated number from {0} and {1} is {2}", miNumber, mNumber, x.Next(miNumber, mNumber)));
}
However, this application works on:
Developer machine if runned with visual studio [debug]
Another PC with .NET 4.0 installed.
My laptop
This application does not work on:
My own computer. If I copy test.exe in another location, it won't run.
I'm sure that I got .NET 4.0 since I run on Windows 8.1, I even tried to install it again but it says I already have it. [Anyways the Visual Studio could'nt make application in .net 4.0 if there wasn't the framework installed]
I've checked Event Viewer and I ain't see anything displayed such as error or something inputted by the system at the moment the application was run.
I tried:
Running the application from CMD [Stucks] [Screenshot added] Screenshot
Running the application from explorer.exe [Stucks and displays the loading cursor like forever]
If I close the console application displayed, the executable is still running. I tried to kill it from CMD using 'taskkill /f /im test.exe' with highest privilege available Killing however, I'm receiving an error at my second try.
The executable is still there, I can't delete or move the exe until I restart the machine.
Thanks for any help provided because I really don't get it what's the issue here.
Thanks to #HansPassant https://stackoverflow.com/users/17034/hans-passant
The problem is from Avast Antivirus.
I've disabled Avast shields and the application is working properly.
I really don't get why avast doesn't like .NET Frameworks so much but, at least is a temporary fix.
Thanks.
I'm pretty sure it could be some kind of anti virus application that's blocking your application.
Update Too late :D
I have a service that I've built using the C# ServiceBase class. It works when I run it in Windows 7 and Windows Server 2008; however, it doesn't work on Windows XP.
I created the service using sc create PBUService binpath= "C:\PBULogger.exe". This is the correct path.
Nothing is logging in the Event Viewer under anything and my exception handling code doesn't fire either.
I thought maybe I didn't have the correct .NET version installed, but I have 4.0 installed on the XP machine. However, I created this project using Visual Studio Express 2012, which I'm pretty sure uses .NET 4.5 by default. Is this causing an issue? All the classes I'm using are version 4.0.
I have stripped down all my code to the base methods and this still doesn't work. Here is my code:
namespace PBULogger {
class PBULoggerService : ServiceBase {
protected override void OnStart(string[] args) {
try {
base.OnStart(args);
} catch (Exception ex) {
EmailUtility.sendEmail("Service Error", ex.Message + ex.StackTrace);
}
}
protected override void OnStop() {
base.OnStop();
}
}
Since it doesn't log in the event viewer, it tells me it isn't even trying to start the service.
I found these entries in my registry for the service under 'HKEY_LOCAL_MACHINE/System/ControlSet001/Enum/Services/PBUService/Enum'.
Not really sure what it means.
Anybody know what's going on?
You must have compiled your exe either for .Net 4.5 or for 64-bit architecture (or both). This is the explanation of error code you run into from WinError.h:
// %1 is not a valid Win32 application.
//
#define ERROR_BAD_EXE_FORMAT 193L
Make sure you have compiled it for x86 platform or Any CPU, and whatever version of .Net Framework you compiled against is installed on the machine.
I found this after googling the windows service error number:
*Generally the error message means that the service manager couldn't find the exact .exe path to run the service. Sometimes, the service is installed from a directory with multiple words for the directory name. So the registry path to the service needs to be placed with double quotes.
Click ‘Start’ and type ‘services.msc’ and hit Enter
Check for the multimedia class scheduler and audio endpoint builder service.
Check for the path under "path to executable:" for both the services. Make a note of the same.
Also make a note of the service name for both the services.
The services are as follows:
AudioEndpointBuilder - AudioEndpointBuilder
Multimedia Class Scheduler - MMCSS
Now, let’s check if the paths under these two services are the same as well in the registry.
Click ‘Start’, type regedit and hit Enter
Locate the following key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
Under services, check for these services: MMCSS and AudioEndpointBuilder.
Corresponding to the above two services, the Image path (on the right pane) should be same as the path in ‘services.msc’*
I found it here
In our case this happened after a server crash and the exe file got corrupted. We re-deployed the binaries and then the service started successfully.
In my case, this was due to building with target of 64-bit only. I forgot that one of my test servers running Server 2003 was 32-bit. My service runs fine on the 64-bit Server 2008 R2 box.
I think that there is a compatibility problem with .net framework that you use and windows server 2003.Do you use .net 4.5? Windows server 2003 can't run applications which target net framework 4.5.
http://www.microsoft.com/visualstudio/eng/products/compatibility
So you could change your target framework to 4.0.
Is there a way to detect if your program was loaded through Visual Studio vs. whether it was started as a standalone executable?
Our software has a bug reporting feature to handle unhandled exceptions -- we need to be able to distribute debug builds to our beta testers, but we don't want the bug report to go off when we are in the middle of development, because the Exceptions are a lot more useful if VS catches them with a full stack trace, etc.
Right now, I'm disabling the bug report if Application.ExecutablePath includes bin\Debug or bin\Release, but I figure there is probably a more robust way of detecting whether the program was loaded through VS.
Obviously, we could set up a different build with some preprocessor macros, but for the sake of the question, assume that isn't a possibility -- I don't mind adding code, but I'm trying to make the fewest modifications to the build process, which is why command-line options are kind of a last resort as well.
If it matters, I'm using VS2003/.NET 1.1.
If you're doing this to determine if it is in any debugger (clarified by #JaredPar), you can use Debugger.IsAttached in the exception handler.
try
{
// ...
}
catch(Exception ex)
{
if (!Debugger.IsAttached)
{
ExceptionHandler.Frob(ex);
}
else
{
throw;
}
}
Alternatively:
public static void Frob(Exception ex)
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
I don't do .net development, but in java I have done this by passing a flag into the startup options of the application. So you could pass a debug flag into the app from the IDE, and then check for that, when the app is run as an executable the flag would not be present. I would be surprised if .net didn't have something similar.
I know this is old but the provided solutions are not very satisfying.
I used the following class instead:
using System.IO;
using System.Reflection;
public static class Program
{
public static string ExecutablePath
{
get;
private set;
}
static Program()
{
var assemblyPath = Assembly.GetEntryAssembly().Location;
var assemblyDirectory = Path.GetDirectoryName(assemblyPath);
if (assemblyDirectory.EndsWith(#"\Debug") || assemblyDirectory.EndsWith(#"\Release"))
{
string projectFile = Path.GetFileNameWithoutExtension(assemblyPath) + ".csproj";
var root = new DirectoryInfo(assemblyDirectory);
while (root.Parent != null)
{
if (File.Exists(Path.Combine(root.FullName, projectFile)))
break;
root = root.Parent;
if (root.Parent == null) // we could not find it (should not happen)
ExecutablePath = assemblyDirectory;
}
ExecutablePath = root.FullName;
}
else
{
ExecutablePath = assemblyDirectory;
}
}
}
Then you can just use Program.ExecutablePath. If you already have a class named Program you can just extend it by those properties and methods.
If running from Visual Studio it will give you the project path where the csproj-file resides. This is the executable path without the "bin\*\Debug" or "bin\*\Release" stuff.
If not running from Visual Studio it will give you the path where the executable resides.
The solution is independent of debug settings, other attached debuggers or build configurations. The only important thing is, that your configurations are named "Release" and "Debug".
Note: As Troy Gizzi mentioned in the comments, this solution only works if you run the executable from another directory than the output directory. For my use case (simulate the deployment directory structure with the project directory as the root directory), this is a suitable solution. In general I copy my executable later to the deployment directory and expect the same behavior as if I run my program from within Visual Studio. Content and other dependencies are located relative to the project directory in my case.
Have you considered command line arguments? Run the program from Visual Studio with a --no-exception-handling flag (or whatever sounds appropriate), and don't handle exceptions if that argument is passed in. When you start the program elsewhere, without this argument, it'll behave normally.
Instead of tracking by process tree, I would add a configuration flag that enables the reporting feature. The flag can always default to "true" unless you are in your DEV environment then you set it to "false".
Sometimes the application is started outside the debugger and the debugger gets attached later. (Doubleclick on a file where the application is assigned to ...) I use this code to wait for the debugger attach.
using System.Diagnostics;
Process[] procName = Process.GetProcessesByName("devenv");
if(procName.Length > 0)
MessageBox.Show("Wait for debugger attach");