Why wont the files in the test folder delete?? How can i get admin access??
namespace Delete
{
using System;
using System.Windows.Forms;
using System.IO;
public class Delete
{
public Delete()
{
if (Directory.Exists(#"C:\Program Files (x86)\test\"))
{
string[] filePaths = Directory.GetFiles(#"C:\Program Files (x86)\test\");
foreach (string file in filePaths) { File.Delete(file); }
}
}
}
}
You need to rethink your strategy.
If you are adding/removing files programatically from within your application, they should be stored in a separate location (that won't need admin privs to elevate for writing/deleting, etc.):
like the user's data directory/your company/your application, or
the user's documents/your company/your application
The Program Files directory is for application specific files (DLL's, etc) that are installed with the program but don't change once installed/updated.
Here's an example of the User's Data directory by application:
public static DirectoryInfo ApplicationVersionDirectory()
{
return new DirectoryInfo(System.Windows.Forms.Application.UserAppDataPath);
}
This is due to the UAC. So either run your executable as admin by right clicking -> "Run as Administrator" or if you want to do it programatically refer to other posts like Windows 7 and Vista UAC - Programmatically requesting elevation in C#
In order to delete files from "Program Files" folder you need to start application as an administrator. Otherwise you will not be able to get an access to %PROGRAMFILES%.
Here is the sample code to restart current app and run it as admin:
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.FileName = Application.ExecutablePath;
proc.Verb = "runas";
try
{
Process.Start(proc);
}
catch
{
// The user refused the elevation.
// Do nothing and return directly ...
return;
}
Application.Exit(); // Quit itself
Related
Someone i know has made a python script that checks validity of some files. Right now that only works local, but he wants it to work cloud based. He gave me the .exe file with a few other files that i can use. I'm using .net core 2 for my backend. I can start the .exe file just fine. But when the python code tries to open the config file he made, the program returns it cannot find the file.
try:
json_data=open('config.txt').read()
except FileNotFoundError:
sys.exit('FATAL ERROR: config.txt not found!') <--returns this
except Exception as e:
sys.exit('FATAL ERROR: {}'.format(e))
The file is in the same folder as the .exe. Whenever i just run it straight from windows it works perfect and it can find the file. But whenever i run the program from within my .net core webapp it gives back that error. I'm using visual studio 2017 for development and debugging.
Here is my c# code i got from a post on stackoverflow to run the exe:
public IActionResult Index(string cmd, string args)
{
try
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "Python\\Windows 64-bit\\mdqt.exe";
start.Arguments = string.Format("\"{0}\" \"{1}\"", cmd, args);
start.UseShellExecute = false;
start.CreateNoWindow = false;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
using (Process process = Process.Start(start))
{
string result = "";
while (!process.HasExited)
{
while (!process.StandardOutput.EndOfStream)
{
result += process.StandardOutput.ReadLine();
}
while (!process.StandardError.EndOfStream)
{
result += process.StandardError.ReadLine();
}
}
return Ok(result);
}
}
catch (Exception e)
{
return Ok(e);
}
}
Could it be some file permissions issue? If so how can i fix it?
EDIT:
I have set the working directory using the following code:
start.WorkingDirectory = Path.Combine(hostingEnvironment.ContentRootPath.ToString(), "Python\\Windows 64-bit");
It now gives me an error it cannot find the folder. Yet when I put the link into the filemanager(and ofcourse delete 1 backslash everywhere), it directs me to the right folder. Could this be a permissions issue? The folder I'm linking to is within the project folder, so IIS should be able to reach that folder as it has permission to interact with the parent folders. What am I overlooking?
I want to make a C# program that deletes a file in system32. The program can delete a file in an normally accessed area such as the desktop but won't find a file in system32, how would I give the program access to system32?
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string filepath = #"C:\Windows\System32\New.txt";
if (File.Exists(filepath))
{
File.Delete(filepath);
}
else
{
Console.WriteLine("File not found");
Console.ReadLine();
}
}
}
}
To begin with you SHOULD NOT delete files from system 32 folder, these files usually belong to OS and should not be tempered with.
Anyways ! i would not ask why you have this requirement but windows User Account Control (UAC) will not allow you perform this operation just like that, You will need to elevate the permissions and take ownership of the file as shown below :
//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:\Windows\System32\toBeDeleted.txt && icacls C:\Windows\System32\toBeDeleted.txt /grant %username%:F");
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
processInfo.FileName = fileName;//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.Delete(#"C:\Windows\System32\toBeDeleted.txt");
return true;
}
catch (Win32Exception)
{
//Do nothing as user cancelled UAC window.
}
When you run this a prompt will be presented to user to confirm this action, if you want to avoid this you'll need to run your entire host process with elevated permissions by Creating and Embedding an Application Manifest (UAC) to require the 'highestAvailable' execution level: this will cause the UAC prompt to appear as soon as your app is started, and cause all child processes to run with elevated permissions without additional prompting.
Hope this helps !
Consider the following statement in a C# console application:
Process.Start("3rdParty/SomeTool.exe");
This statement starts SomeTool.exe in the 3rdParty folder relative to... what, exactly? The folder where the application's .exe resides? The current working directory (which can be changed during the application's lifetime)? Something else?
It is relative to the current working directory of your process.
You can determine your current working directory using Directory.GetCurrentDirectory() and change it using Directory.SetCurrentDirectory().
Well, why don't we find out?
Let's create a simple console application and have some fun with it:
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
Directory.CreateDirectory("Test");
Console.WriteLine($"Absolute path is: { Path.GetFullPath("Test")}");
Console.ReadLine();
}
}
}
Build it in release mode (we are deploying it after all) and put it in some accesible location. Now double click on it and see what output you get.
Absolute path is: {SomeAccesibleLocationPath}\Test
Hmmm, it seems like the relative path is relative to the directory where the executable was launched. Is this always so?
Let's build another app, we'll call it ConsoleApplication2, and play some more:
class Program
{
public static void Main()
{
Console.WriteLine($"TEST #1: {LaunchProcessAndGetAbsolutePath()}");
Console.WriteLine($"TEST #2: {LaunchProcessAndGetAbsolutePath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))}");
Console.ReadLine();
}
private static string LaunchProcessAndGetAbsolutePath(string workingDirectory = null)
{
var startInfo = new ProcessStartInfo(#"{SomeAccesibleLocationPath}\ConsoleApplication1.exe");
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
if (workingDirectory != null)
{
startInfo.WorkingDirectory = workingDirectory;
}
using (var p = Process.Start(startInfo))
{
var ret = p.StandardOutput.ReadLine();
p.StandardInput.WriteLine();
p.WaitForExit();
return ret;
}
}
}
If we run this, you'll see that the output is the following:
TEST #1: {MyConsoleApplication2ExecutableDirectory}\Test
TEST #2: {MyDocumentsPath}\Test
Important facts to consider:
The relative paths are always relative to the working directory.
When starting a process from another process, the default working directory is the working directory of the "parent" process, its not the directory of the launched "child" process.
When launching a process by double clicking on the executable, the working directory is set to the executable's directory.
In general, the working directory need not be the executable's directory. Your program's correctness should not rely on this condition ever.
As mentioned, it is relative to the current working directory. The value can be changed and determined via Directory.SetCurrentDirectory(), resp. Directory.GetCurrentDirectory()
Some notes:
The current working directory CAN be the folder where the executable resides; this is the default working directory if none is specified. But it can also be set to a different folder when a process is started or while running. On start either by setting the property ProcessStartInfo.WorkingDirectory when launching a process, or also by using the working directory field in the symbolic link dialog in e.g. the start menu. The latter can be done by a user. The current working directory CAN also be changed by any 3rd party library that is being loaded into the process.
Therefore relative paths in an application without checking the working directory are unreliable and usually cause unexpected behavior.
Is there any way to recognize if the application has been run from a shortcut instead of executable file? I need to make my users to copy exe file to their desktops rather than create shortcuts to it due to personalization issues. Any ideas?
Edit: creating the installer is not an option.
I don't know if this helps, but if you want your exe file to be on the desktop, this could work:
string path = Directory.GetCurrentDirectory();
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (!path.Equals(desktopPath))
{
Console.WriteLine("file is not at desktop");
}
If you do have an app in the windows shared folder you can configure it to prevent execution of the applications.
Or you can provide user just with link to .bat file instead of .exe and it would do something like this (using robocopy):
robocopy \\remote\server\exe %AppData%\your\folder app.exe /XO
start %AppData%\your\folder\app.exe
And on the C# side you can just check application path and do something like this:
public class Program
{
public int Main()
{
string original_path = System.IO.Path.GetFullPath(#"\\remote\app.exe");
string current_path = System.IO.Path.GetFullPath(
System.Reflection.Assembly.GetExecutingAssembly().Location);
if(original_path == current_path){
System.IO.File.Copy(original_path, #"C:\foo\bar\app.exe", true);
System.Diagnostics.Process.Start(#"C:\foo\bar\app.exe");
return 0;
}
// Run program normally here
}
}
i cannot create file in my windows service
and this is error
error In onstart method Access to the path 'C:\Windows\system32\BridgeServiceLog.txt' is denied.
protected override void OnStart(string[] args)
{
try
{
Logger.InitLogFile("BridgeServiceLog.txt");
Trace.WriteLine(Logger.logSwitch.TraceInfo, "Trace Started");
Trace.WriteLineIf(Logger.logSwitch.TraceInfo, "OnStart Started");
_bridgeServiceEventLog.WriteEntry("new OnStart");
if (Vytru.Platform.Bridge.Configuration.LicenseValidetor.ValidCountAndTypeDevices())
{
SharedData.InitializeBridge();
// WsInitializeBridge();
}
else
{
this.Stop();
_bridgeServiceEventLog.WriteEntry("LicenseValidetor Error");
}
_bridgeServiceEventLog.WriteEntry("end Start");
}
catch (Exception e)
{
Trace.WriteLineIf(Logger.logSwitch.TraceError, e.Message);
_bridgeServiceEventLog.WriteEntry("error In onstart method " + e.Message);
}
Trace.WriteLineIf(Logger.logSwitch.TraceInfo, "OnStart Ended");
}
The service user account probably doesn't have access to write to C:\Windows\System32 (which is the working directory of a Windows service).
Anyway, you shouldn't write to that folder. It is for the operating system - not your service.
You can use Environment.GetFolderPath to get a suitable path for writing files like log files in a way that will work any computer, not just your own computer. Here is an example.
var companyPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"MyCompany"
);
var productPath = Path.Combine(companyPath, "MyProduct");
var logFilePath = Path.Combine(productPath, "BridgeServiceLog.txt");
You should of course use suitable values for MyCompany and MyProduct.
When running a Windows Service the default working folder is <System drive>:\Windows\System32\.
Fortunately, not everyone can just access that folder.
There are two ways about this; write your file to another folder to which you do have rights, or run your service with administrator rights.
I would recommend the first option.
The easiest solution is to go the folder where you want to save a file, right click, properties, security, add a new user IIS_Users and give permission to write.
Use LocalSystem account on ProjectInstaller