Overwrite restricted application file? - c#

I'm trying to manually patch my application. The application makes use of a Service which i make sure to stop and uninstall prior to attempting any overwriting of the application dll's.
The issue is that i can't overwrite, or even delete some of the dll files which are the core of the application, these dll files are used by the service i uninstalled first.
I use the following method to pass in the new file-path in order to replace the old DLL which is located inside the root directory of the application in C:\Program Files\AppName\
public static bool CopyFile(string newFile, string oldFile)
{
var newfile = new FileInfo(newFile);
var oldfile = new FileInfo(oldFile);
var f2 = new FileIOPermission(FileIOPermissionAccess.AllAccess, oldFile);
f2.AddPathList(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, newFile);
try
{
f2.Demand();
}
catch (SecurityException s)
{
Console.WriteLine(s.Message);
}
for (int x = 0; x < 100; x++)
{
try
{
File.Delete(oldfile.FullName);
newfile.CopyTo(oldfile.FullName, true);
return true;
}
catch
{
Thread.Sleep(200);
}
}
return false;
}
I just wish to provide a new file and remove the old one, replace it, overwrite it.... The application
Note: The application i run to do the patching runs as administrator.
Any idea?

I was able to fix this issue by making use of a "middle man" in other words, another application which downloads another executable and passes command line arguments to it.
Originally, my service would download an executable (call it Installer.exe). Installer.exe would then attempt to stop the service and patch the content, this did not work.
I now have the service running, it downloads "Installer.exe".
Installer.exe will load up and download PatchPayload.exe.
PatchPayload.exe runs and kills off the Service, uninstalls it and then download all required patch content from a centralized server and patch the service core files individually then install the service and run it again.

Related

SharpSvn.SvnException: sqlite[S8]: attempt to write a readonly database

I got following error when I do `
svnclient.CleanUp(WorkDirPath);`
SharpSvn.SvnException: sqlite[S8]: attempt to write a readonly database
---> SharpSvn.SvnException: Additional errors:
---> SharpSvn.SvnException: sqlite[S8]: attempt to write a readonly database
Update
I have visual studio application and from this application i need upload/download any file to SVN server and this feature can access by end user. so for this i installed VisualSVN Server Manager Version: 4.3.3 on windows server. in my application i imported nuget for this SharpSvn.1.8-x64 to atchive this task (I am new in subversion and client).
Updated : I updated sharpSVN to 1.14001.156 thanks for it. but still my problem is not solved. i still get following error when try to add file "Failed to lock working copy" and then I tried Clean Up Command got "sqlite[S8]: attempt to write a readonly database" error. Is Visual SVN Server Version: 4.3.3 ok with SharpSVN 1.14 ?
following is my code written in C#
svnclient.Authentication.DefaultCredentials = new NetworkCredential(_svnuser, _svnpwd);
CleanCommand(svnclient,_userworkdir);
public bool AddFile(string path, SvnClient svnclient)
{
try
{
return svnclient.Add(path);
}
catch (Exception ex)
{
Log.Error(String.Format(String.Format("Exception in function AddFile := {0} FilePath :- {1}", ex.Message.ToString(), path)));
return false;
}
}
public bool CleanCommand(SvnClient svnclient, String workingdir)
{
bool res = false;
try
{
res = svnclient.CleanUp(workingdir);
}
catch (Exception ex)
{
Log.Error(String.Format(String.Format("Exception in function CleanCommand := {0}, workingdir :- {1}", ex.Message.ToString(), workingdir)));
res = false;
}
return res;
}
Note that SharpSVN 1.8 is outdated. If you use Subversion client based on SharpSVN (AnkhSVN?), it makes sense to update it or to switch to an up-to-date native Subversion 1.14.x client.
As an immediate solution, you can check out a new working copy and continue you work with it. If you have uncommitted changes in the working copy, you can copy them over into a new working copy (don't copy hidden .svn directory though).
I think that something prevents you from opening or writing the contents of the .svn metadata directory. This could be due to insufficient permissions or another program that locks your working copy:
Check NTFS permissions to the .svn directory in the root of your working copy and the .svn/wc.db file in particular (e.g., C:\Users\MyUser\MyVsProject\.svn\wc.db). You should double-check that your user account has permissions to write to C:\Users\MyUser\MyVsProject\ directory and all its contents.
Check if other SVN clients or programs work concurrently with your client and lock the working copy.

.net core can't open file from python script

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?

Programmatically check if a windows service is running c#

I am writing an app to check to see if certain software is installed. One of my cases im looking for a service. I know the full path of the service. i.e. "c:\some folder\MyService.exe" I want to check to see if the service is installed and running. I have tried process.GetProcessbyName, but running into issues with 64 bit vs 32 bit processes. I've also tried ManagementObject but i keep getting invalid object path. Is it possible to get a service knowing only the path to the executable?
I know only the name and path of the executable. There may be more than one version of the executable as well, each with a different service name, which i do not have.
Here is how you can check if the service is installed or not , also get the status of the service
public static string CheckService(string ServiceName)
{
//check service
var services = ServiceController.GetServices();
string serviceStatu = string.Empty;
bool isServiceExist = false;
foreach (var s in services)
{
if (s.ServiceName == ServiceName)
{
serviceStatu = "Service installed , current status: " + s.Status;
isServiceExist = true;
}
}
if (!isServiceExist)
{
serviceStatu= "Service is not installed";
}
return serviceStatu;
}
Console.WriteLine(CheckService("Service name"));
you need to add System.ServiceProcess to the project reference
Try looking into the ServiceController / Management object for the executable path. Then based the executable path determine whether the service is running.
How to get executable path : [1] [2] [3]
Borrowed from an answer above
ManagementClass mc = new ManagementClass("Win32_Service");
foreach(ManagementObject mo in mc.GetInstances())
{
if(mo.GetPropertyValue("PathName").ToString().Trim('"') == "<your executable path>")
{
return mo.GetPropertyValue("Name").ToString(); // or return true;
}
}
I haven't tested this, and a comment suggested PathName may return command line arguments as well, so you may need to write another method to separate the path from the arguments (I'm assuming it'll just be a split on the string), and pass PathName to it in If statement..

Why can't I install my windows service - Specified service already exists

I wish I could put a grenade to my computer at this point. I'm so frustrated because I don't understand why my application won't install using installUtil.
I've just looked through this link now: Windows Service Install Ends in Rollback and unfortunately the kind suggestions on there don't help in my situation, the following error was generated after taking into consideration all of the answers posted by the good people of SO on that link and others.
I have looked for best practices on the web for task parallel processing patterns but there's nothing helpful so far. The latest error I get when attempting to install is as follows:
.exe assembly's progress. The file is located at
E:\xxx\MyService\Service_V2.InstallLog. Installing assembly
'E:\xxx\MyService\Service_V2.exe'. Affected parameters are:
logtoconsole = logfile = E:\xxx\MyService\Service_V2.InstallLog
assemblypath = E:\xxx\MyService\Service_V2.exe Installing service
Service V2... Service Service V2 has been successfully installed.
Creating EventLog source Service V2 in log Application... Installing
service Service V2... Creating EventLog source Service V2 in log
Application...
An exception occurred during the Install phase.
System.ComponentModel.Win32Exception: The specified service already
exists
The Rollback phase of the installation is beginning. See the contents
of the log file for the E:\xxx\MyService\Service_V2 .exe assembly's
progress. The file is located at
E:\xxx\MyService\Service_V2.InstallLog. Rolling back assembly
'E:\xxx\MyService\Service_V2.exe'. Affected parameters are:
logtoconsole = logfile = E:\xxx\MyService\Service_V2.InstallLog
assemblypath = E:\xxx\MyService\Service_V2.exe Restoring event log to
previous state for source Service V2. Restoring event log to previous
state for source Service V2. Service Service V2 is being removed from
the system... Service Service V2 was successfully removed from the
system.
The Rollback phase completed successfully.
The transacted install has completed. The installation failed, and the
rollback has been performed.
There was nothing written to the event log either.
Here is my OnStart() method:
protected override void OnStart(string[] args)
{
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
ErrorLogFileName = "Service_V2Errors" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
Service_V2LogFile = "Service_V2Log" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
ErrorLogPath = ConfigurationManager.AppSettings["Errorpath"].ToString();
CheckBatchRecord = Convert.ToInt32(ConfigurationManager.AppSettings["CheckBatchTime"].ToString());
if (!Directory.Exists(ErrorLogPath))
{
Directory.CreateDirectory(ErrorLogPath);
}
LogMessage("Starting Service " + DateTime.Now.ToString());
_ErrorLog = new StreamWriter(ErrorLogPath + "//" + ErrorLogFileName, true);
_ErrorLog.WriteLine("Error, Location, AdditionalInformation", true);
_ErrorLog.Close();
var t = Task.Run(() => Service_V2Start(), token);
try
{
t.Wait();
}
catch (AggregateException e)
{
LogMessage("Exception messages:");
foreach (var ie in e.InnerExceptions)
LogMessage(ie.GetType().Name + " : " + ie.Message);
LogMessage("\nTask status: " + t.Status);
}
finally
{
tokenSource.Dispose();
}
}
I have also set the compile mode to release for the final install files compiled.
I have done an "sc delete Servie V2" and I also checked the services console and there is no such service listed there.
I have also tried the InstallUtil.exe -u command to uninstall, but I still get this nitwit error. What should I do now?
Make sure your Program.cs file looks something like this:
static class Program
{
static void Main()
{
var service = new YourServiceName();
ServiceBase.Run(service);
}
}
Inside the InitializeComponent() method make sure that the ServiceName property value is the same as the ServiceName in the ProjectInstaller.cs
this.ServiceName = "MyServiceName";//in the YourServiceName partial class
this.myServiceInstaller.ServiceName = "MyServiceName";//in the installer
Make sure you have only one installer.
In the batch files that you created to install and uninstall your service make sure that you are pointing to the correct InstallUtil.exe.
For 64 bit architectures you can use - C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe
For 32 bit architectures you can use - C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe
Sample InstallService.bat file:
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe" "PathToTheExecutables\MyServiceName.exe"
pause
Sample UninstallService.bat file:
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe" /u "PathToTheExecutables\MyServiceName.exe"
pause
Make sure you run cmd as Administrator :)

Can I run a ASPX and grep the result without making HTTP request?

How can I just make a function call, without URL, and without HTTP, to a simple ASP.NET file, and capture the byte stream it generated?
More background information,
I need a some kind of template can put a little logic inside, to render some INI like text files. I give up those libraries ported from Java and come up a solution of using ASP.NET for template engine. (I am NOT using it to build a website, not even a HTML.)
I have written a ASP.NET page (no WebForm, no MVC), which accept a XML POST, and it generate a long text file based on a set of simple but not too simple rules.
I generate the XML from DB objects, submit to the ASP page, grep the result and it works very well. However, the problem is that we want to use as a library, using by a WCF. Because of this, I failed to use a relative path and I have to store the URL of the ASP somewhere in the configuration, which I do not want to.
It will be hosted on a IIS server, but not called (at least not directly) from any frontend ASP, and will never called from end user.
PS. I was originally looking for a simple template engine for C#, but they are too old and not maintenance anymore, poor documentation, missing integrated editor/debugger, too simple, and the they might speak different languages.
PPS. I've also thought about T4, but it does not have a editor nor debugger in VS 2008.
You can run an ASPX page without IIS, without an HTTP message, if you build a host for the ASPNET runtime.
Example:
public class MyAspNetHost : System.MarshalByRefObject
{
public void ProcessRequest(string page)
{
var request = new System.Web.Hosting.SimpleWorkerRequest
(page, // the page being requested
null, // query - none in this case
System.Console.Out // output - any TextWriter will do
);
// this will emit the page output to Console.Out
System.Web.HttpRuntime.ProcessRequest(request);
}
public AppDomain GetAppDomain()
{
return System.Threading.Thread.GetDomain();
}
}
public class Example
{
public void Run(IEnumerable<String> pages)
{
// ASPNET looks for assemblies - including the assembbly
// that contains any custom ASPNET host - in the bin\
// subdirectory of the physical directory that backs the
// ASPNET Host. Because we are going to use the current
// working directory as the physical backing directory for
// the ASPNET host, we need to ensure there's a bin
// subdirectory present.
bool cleanBin = false;
if (!Directory.Exists("bin"))
{
cleanBin = true;
Directory.CreateDirectory("bin");
}
// Now, ensure that the assembly containing the custom host is
// present in that bin directory. The assembly containing the
// custom host is actually *this* assembly.
var a = System.Reflection.Assembly.GetExecutingAssembly();
string destfile= Path.Combine("bin", Path.GetFileName(a.Location));
File.Copy(a.Location, destfile, true);
host =
(MyAspNetHost) System.Web.Hosting.ApplicationHost.CreateApplicationHost
( typeof(MyAspNetHost),
"/foo", // virtual dir - can be anything
System.IO.Directory.GetCurrentDirectory() // physical dir
);
// process each page
foreach (string page in pages)
host.ProcessRequest(page);
}
}
If you want to clean up that bin directory, you have to get the AppDomain to unload first. You can do that, like this:
private ManualResetEvent aspNetHostIsUnloaded;
private void HostedDomainHasBeenUnloaded(object source, System.EventArgs e)
{
// cannot clean bin dir here. The AppDomain is not yet gone.
aspNetHostIsUnloaded.Set();
}
private Run(IEnumerable<String> pages)
{
try
{
....code from above ....
}
finally
{
if (host!= null)
{
aspNetHostIsUnloaded = new ManualResetEvent(false);
host.GetAppDomain().DomainUnload += this.HostedDomainHasBeenUnloaded;
AppDomain.Unload(host.GetAppDomain());
// wait for it to unload
aspNetHostIsUnloaded.WaitOne();
// optionally remove the bin directory
if (cleanBin)
{
Directory.Delete("bin", true);
}
aspNetHostIsUnloaded.Close();
}
}
}
This makes sense for testing ASPX pages, and that sort of thing. But I'm not so sure this is the right thing, for your scenario. There are more direct ways to generate text files. But, it may be right for you. If you really like the template engine idea, hosting ASPNET may be just the thing for you.
In your case, you would want to modify the custom Host so that the output for each page goes to a StringWriter instead of Console.Out, and then you could do Grep (or more likely a search with Regex) on that output. You might also want to modify it to accept all the input data as a querystring. You'd need to format the page request to do that.
EDIT: There's a good article on MSDN Magazine on this technique of hosting the ASPNET runtime. From December 2004.
EDIT2: There's a simpler way to manage the bin directory. Just create a symbolic link named bin, pointing to ".". Then, you can remove the symlink after the call to AppDomain.Unload(), without waiting. Looks like this:
public void Run(string[] pages)
{
bool cleanBin = false;
MyAspNetHost host = null;
try
{
// This creates a symlink.
// ASPNET always looks for a bin\ directory for the privateBinPath of the AppDomain.
// This will create the bin dir, pointing to the current dir.
if (!Directory.Exists("bin"))
{
cleanBin = true;
CreateSymbolicLink("bin", ".", 1);
}
host =
(MyAspNetHost) System.Web.Hosting.ApplicationHost.CreateApplicationHost
( typeof(MyAspNetHost),
"/foo", // virtual dir - can be anything
System.IO.Directory.GetCurrentDirectory() // physical dir
);
foreach (string page in pages)
host.ProcessRequest(page);
}
finally
{
// tell the host to unload
if (host!= null)
{
AppDomain.Unload(host.GetAppDomain());
if (cleanBin)
{
// remove symlink - can do without waiting for AppDomain unload
Directory.Delete("bin");
}
}
}
}
This eliminates the need for the ManualResetEvent, copying files, synchronization, etc. It assumes the assembly for the custom ASPNet Host as well as all the assemblies required by the ASPX pages you run are contained in the current working directory.
This sounds like a very similar issue which is generating HTML emails on a server. There are some answers here that do that (for MVC):
ASP.NET MVC: How to send an html email using a controller?
You can proceed in a similar fashion for non-MVC by loading and rendering a control (ASCX) to a file.

Categories

Resources