Can't delete a service executable after uninstalling it - windows-services

I'm uninstalling a service like this:
using (AssemblyInstaller installer = new AssemblyInstaller(serviceFileName, new String[] { }))
{
installer.UseNewContext = true;
installer.Uninstall(null);
}
which works fine, but then I try to do a Directory.Delete, and it throws an exception saying that access to the service's executable was denied. Yet immediately after, I can delete the file manually in windows explorer.
My application is being run by an installer that requests admin access, so I'm assuming that it has rights to the file. In fact, it deletes all of the other files in that directory, it just can't get that one. I also checked and the file isn't read only.
Any ideas why I can't delete this file?

It turns out that there's a handle to that file that stays open. The solution was to create a new AppDomain, that the installer runs in, and to close it before trying the delete:
var domain = AppDomain.CreateDomain("MyDomain");
using (AssemblyInstaller installer = domain.CreateInstance(typeof(AssemblyInstaller).Assembly.FullName, typeof(AssemblyInstaller).FullName, false, BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.ExactBinding, null, new Object[] { serviceFileName, new String[] { } }, null, null, null).Unwrap() as AssemblyInstaller)
{
installer.UseNewContext = true;
installer.Uninstall(null);
}
AppDomain.Unload(domain);

Related

Microsoft Graph API to Stop Inheriting Permissions in One Drive items

In the OneDrive user interface, it is possible to update a drive item so that the permissions no longer inherit from the parent (Stop Inheriting Permissions). Is it possible to do the same through the Graph API? I can seem to find any call that seems to allow for that. In the documentation for Delete Permissions, it says:
"Only sharing permissions that are not inherited can be deleted. The inheritedFrom property must be null."
We need to be able to programatically set the permissions on drive folders and items and one of the things we have to do is to stop inheritance from parent.
Regards,
LT
i know it's a long time question but here what you can do :
Get the directory item Id
Get the permissions id list
=> https://graph.microsoft.com/v1.0/me/drive/items/{itemId}/permissions
Loop over all permissionIds and delete them
Post a new Invite with all the users/groups you want
The "inherited" is only a list of allow users/groups ... if you delete all of them, your folder become a "only you" folder permission (no inheritance)
I use that in my application, it's not the most simple but it works
I am also struggling with the Graph Api invite-endpoint https://learn.microsoft.com/en-us/graph/api/driveitem-invite?view=graph-rest-1.0&tabs=http
I have not found an better solution than #Dadv.
My job is to copy an Sharepoint folder to another folder, including any subfolders.
And then make sure that subfolders get the exactly same permissions as the source subfolders.
Unfortunaly this has to be 2 seperate tasks, when using the Graph Api, using /copy endpoint to copy the subfolders, and for the permissions I use a combination of Delete / Update / Add to syncronize the permissions.
Rather complicated with lots of roundtrips to the API, for such a simple job.
Now I hope to hear from someone who knows of an simpler way of doing the permission part.
Here is some pseudo code to show visualize the syncronization of the permissions.
// Now the targetFolders exists --> syncronize permissions
var targetFolderGraphUr = "https://graph.microsoft.com/v1.0/drives/<id>/items/<item-id>";
// First remove all permissions not existing in the sourcefolder
foreach (var targetPermission in targetFolderPermissions)
{
if (!sourceFolderPermissions.FirstOrDefault(p => p.GrantedTo?.User?.DisplayName == targetPermission.GrantedTo?.User?.DisplayName))
{
var deleteUrl = $"{targetFolderGraphUr}/permissions/{targetPermission.Id}";
var deleteResult = await myHttpClient.DeleteAsync(deleteUrl);
}
}
// Then apply permissions from template: Update (Patch) or Add (using /invite)
foreach (var sourcePermission in sourceFolderPermissions)
{
var pcPerm = targetFolderPermissions.FirstOrDefault(p => p.GrantedTo?.User?.DisplayName == sourcePermission.GrantedTo?.User?.DisplayName);
// Update
if (pcPerm != null)
{
bool isUpdateNeeded = CheckIfUpdateNeeded(...);
if (isUpdateNeeded)
{
var updateUrl = $"{targetFolderGraphUr}/permissions/{sourcePermission.Id}";
var updateResult = await myHttpClient.PatchAsync(updateUrl, sourcePermission);
}
}
else
{
// Add
var userId = sourcePermission.GrantedTo?.User?.Id;
var invitePermission = new InvitePermission()
{
Recepients = GetRecepientArray( userId ), // returns a list of recipients, setting objectId = userId
ObjectId = userId,
Roles = sourcePermission.Roles,
RequireSignIn = true,
SendInvitation = false,
};
var inviteUrl = $"{targetFolderGraphUr}/invite";
var inviteResult = await myHttpClient.PostAsync(inviteUrl, invitePermission);
// response is 200 OK, but no permissions are added.
// Using Dadv's workarround, deleting all permissions on targetfolder first, then it works.
// (not shown in this example)
}
}

facing error while uploading file in mvc5 on server

I have MVC5 application , where I need to upload file excel and then then create data table of this excel. I use devexpress control to upload file. I use following code to store uploded file and then read in datatable and then store in database.
if (e.UploadedFile.IsValid)
{
e.UploadedFile.SaveAs(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/" + e.UploadedFile.FileName));
var Filepath = System.IO.Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/" + e.UploadedFile.FileName));
DataTable dtReport = new DataTable();
try
{
dtReport = CreateDataTableFromExcelFile(Filepath, "A1:U", true, "Sheet1").Tables[0];
}
catch
{
}
SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
con.Open();
System.Data.SqlClient.SqlBulkCopy sqlcopy = new System.Data.SqlClient.SqlBulkCopy(con);
sqlcopy.DestinationTableName = "table_Name";
sqlcopy.WriteToServer(dtReport);
con.Close();
If I host this application on IIS on my machine then it works fine. But If I host it on another server then it shows error
Access to the path 'C:\inetpub\wwwroot\MVC_Project_v3\App_Data\UploadTemp\dxupload_19aafa62643d42418b2fe5eaadede3cfcugxrc4e.nrt.tmp' is denied.
Please suggest right solution
The credential you are using to host the WebSite (the credential you enter in the application pool identity) does not have the privilege to access that directory.
Add a valid credential here.

Folder is not accessible to Windows Service

I created a simple Windows Service as a test. All the service does is create a text file on the local drive. This emerged because the my production service was unable to drop a file in a new share that had been established, however I am not able to get this to work in my local workstation.
try
{
if (!Directory.Exists(filePath))
{
logger.Warn(string.Format("Specified folder {0} does not exist.", dropFolder));
}
else
{
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(fileContent);
logger.Debug(string.Format("File {0} has been written.", filePath));
}
}
}
catch (Exception ex)
{
logger.Error("Unable to write the file " + filePath, ex);
}
The service is not able to see the folder, even though it exists. I've changed the Login of the service to an account that is a local admin and set the permissions on the folder to full control for that user.
Is there something special that is required when the user is logged on as a service?

File.Move on client machine Asp.net MVC

Silly question but here goes...
Is it possible to write an intranet windows auth asp.net mvc app that uses File.Move to rename a file on a users machine? Or will the File.Move and using Path.GetDirectory and other System.IO functions look on the IIS server directory structure instead of the client machine?
[HttpPost]
public ActionResult Index(HttpPostedFileBase file, string append)
{
try
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
DirectoryInfo filepath = new DirectoryInfo(file.FileName);
string parentpath = Path.GetDirectoryName(filepath.FullName);
DirectoryInfo searchablePath = new DirectoryInfo(parentpath);
var directories = searchablePath.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo d in directories)
{
if (!string.IsNullOrEmpty(append) && !d.Name.Contains(append))
{
string fName = Path.GetFileNameWithoutExtension(d.Name);
string fExt = Path.GetExtension(d.Name);
System.IO.File.Move(d.FullName, Path.Combine(d.DirectoryName, fName + append + fExt));
}
}
}
}
catch (Exception ex)
{
}
return View();
}
I have tried this but am getting a filenotfoundexception.
Any ideas?
The ASP.NET code runs on the server, so it will look at the files on the server.
You can't rename a file on the client machine, however it would be possible to rename a file on the computer that is used as client, if:
the server and computer are on the same network
the server knows the name of the computer
the server knows which folder to look for in the computer
the folder is shared with the user account running the ASP.NET code on the server with enough privileges to change the name of a file
In that sense the computer is not a client to the server, but the server communicates directly with the computer via the file system, not via IIS.
These will indeed work only on the server.
You may look at the various file and filesystem related specifications for client-side javascript APIs provided by the user's browser:
http://www.w3.org/TR/FileAPI/
http://www.w3.org/TR/file-system-api/
http://www.w3.org/TR/file-writer-api/

Deleting an uploaded file from the server in ASP.NET MVC3

I am trying to upload files to a folder from the admin side like a CMS.
The front-end will display links to download the file.
On the admin end, I would like to not only delete the reference to but also remove the actual file from the server.
Here is the part of my controller that saves the uploaded file:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
ViewBag.fileName = fileName.ToString();
return RedirectToAction("Create", new {fileName = fileName });
}
return RedirectToAction("Index");
}
In the Create view, the admin is then allowed to enter other details about the document and that is stored on a table along with the fileName.
Now I need to be able to link to that document name like document.pdf. Am I even able to link to an uploads folder under App_Data folder?
Also, how do I remove the file and not just the table row on doing delete?
Create a separate controller to handle the downloading of the file. It also prevents your users to hotlink directly to the files.
public ActionResult GetDocument(String pathName)
{
try
{
Byte[] buffer = DownloadMyFileFromSomeWhere(pathName);
FileContentResult result = new FileContentResult(buffer, "PDF"); // or whatever file ext
// these next two lines are optional
String[] folders = pathName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
result.FileDownloadName = folders[folders.Length - 1];
return result;
}
catch (Exception ex)
{
// log the error or something
}
return new HttpNotFoundResult();
}
Where DownloadMyFileFromSomeWhere(string) should be able to retrieve the byte-array file from some storage like a blob or even the local server. It can look something like:
private Byte[] DownloadMyFileFromSomeWhere(string pathname)
{
Byte[] file = System.IO.File.ReadAllBytes(Server.MapPath(pathname));
return file;
}
For the Admin side, you can do the same approach: Write a separate controller to delete the file and its entry in the database.
Some notes:
If you have rights to save a file somewhere, you should also have the rights to delete it. You can use normal file operations to do this.
IIS should block you from linking to a file under App_Data. You have a couple of options:
Create an action that reads the file from that location and streams it back to the browser
Store in a different location - somewhere that the user will actually have access to.
The benefit of the first option is that you can easily add authentication, etc. to your action to secure access to the files, whereas the second option would require you to add a web.config in the folder with the appropriate roles and access rights. However, on the other hand, you'll have to supply appropriate headers in your action method so the browser knows what to do with the file, rather than letting IIS figure it out for you.

Resources