how to update self contained asp.net core app and avoid file locks - asp.net-core

I have a self hosted asp.net core app deployed and in use in an enterprise environment on Windows Server 2012.
I am looking for a way to automate the update process, I am currently doing this through a bat file but keep getting windows file lock errors where the file cannot be deleted. The process I am following in the bat file is as follows:
kill the dotnet core process for the web app
clear the directory (after sleep for a couple of seconds)
copy the updates over
restart the web app
I am getting the errors in 2 where I try to clear out the existing directory which still has file locks even though I have killed the process - "Cannot delete output file - access is denied".
My question is how can I upgrade the self contained asp.net core web app in place and avoid the file locks? If the site is offline for a few seconds it is not an issue.
Thanks

There a several reasons i can think of that deleting the directory gives access denied errors.
Your process isn't actually stopped yet. I know you can use powershell to await until porcess is stopped. (or check if process is stopped yet and otherwise wait 3 more seconds)
Another process still runs in this folder. (maybe even a command line, or explorer.exe is opened in the folder.)
You need admin rights to delete this folder.
The bat file you are executing executes from this directory, and itself is locking the directory.
Try one of the following:
powershell Stop-Service.
It should wait until service is really stopped.
powershell Wait-Process Waits untill process is stopped. you can call this directly after Stop-Process
Try to run powershell to wait like this for example (in commandline):
powershell -Command "Wait-Process -Name MyProcess"`
(warning you might run into ExecutionPolicy problems)
Tip
Use msdeploy, you can remote execute commands and deploy your application.
You can use pre and post scripts (to stop and start the app) and msdeploy it self will sync the folder/directory for you.

Related

Kestrel server doesn't work when run in background, why?

I have a project made and tested with Visual Studio. It works.
Then I uploaded it into Ubuntu server.
Then ran it with dotnet run. Works, remote machines see it (via nginx proxy).
Then I tried dotnet run &. The process seems like started, but nothing listens on port specified. Then, according to the example, I tried sudo nohup dotnet run kestrel > /dev/null 2>&1 &. This time it listened for a while, then died with:
Application started. Press Ctrl+C to shut down.
fail:
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
An unhandled exception has occurred: Can not find compilation library location for package 'google.protobuf'
System.InvalidOperationException: Can not find compilation library
location for package 'google.protobuf' at
Microsoft.Extensions.DependencyModel.CompilationLibrary.ResolveReferencePaths()
(A fragment of output from nohup.out, first linens, I skipped project details as irrelevant and private).
Any clues what's happening? I still get no errors when running it in foreground.
Here's what I found out: I can't run it (it gives same error messages) when I run it as root. On my test server I have a special user account named "dotnet". When I log in as dotnet I can run the app. As root I can't.
I don't want to run my app with root privileges.
Next try: I run dotnet restore as root. Then I go with nohup dotnet run kestrel > /dev/null 2>&1 & and it works.
Nice. Now is there a way to start my app with limited privileges?
I found the answer myself, so I'll share.
First: do not run .NET core projects on Linux as root if you don't intend to give them full root privileges. I think web applications with root privileges are bad idea and sort of asking for troubles.
But well, when something doesn't work, it's tempting to use sudo from time to time. And it turns out it was the cause of the problem:
dotnet restore and dotnet run must be executed with the same privileges, by the same user. When I issued dotnet restore as root, it worked. It's even harder the other way, when you want to run the project as user with lower privileges. You have to remove all temporary files before issuing dontet restore. So, generally nohup dotnet run kestrel > /dev/null 2>&1 & works as charm, no sudo is needed here, running this as root can be harmful.
Now I always create special dotnet user to run dotnet apps on servers. It's safer this way. The user cannot sudo. When I need to perform administrative tasks I just start separate root session. I use the same approach with database access. The app has only rights to execute procedures, not even select allowed.

Running a program at login as admin

I have a program I wrote in Visual Basic Express 2013 to put a classification banner at the top of the screen. I set up a scheduled task using ngen.exe which makes it run at login. The problem is that it doesn't run as admin so any non-privileged user can kill the task.
This program is to replace another program called Netbanner because there are a few issues with Netbanner. The program I wrote resolves all of these issues except for the admin issue. Netbanner is implemented exactly the same way (ngen.exe) but it won't let a non-privileged user kill the task.
I don't know if it is something in the program itself or I missed something in the deployment process.
This is the command used to deploy Netbanner which I duplicated to deploy mine:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe install "C:\Program Files\Microsoft\NetBanner\NetBanner.exe"
Also, these are the files in C:\Program Files\Microsoft\NetBanner:
NetBanner.exe
NetBanner.InstallState
NetBanner.pdb
NetBannerSchTask.xml
Any ideas?
Thanks.
You could try to go into the properties->Compatibility->Run this program as an administrator for the application.
Alternatively, you could do the same thing for a batch file that you can schedule to run on startup.

Endeca Forge failure move_dgraph-input_to_dgraph-input-old

I have an intermittent issue when distributing indexes :( All servers are Windows Server 2008.
I have two servers to distribute to and one of them has failed twice with this error:
INFO: [MDEXHost1] Starting shell utility 'move_dgraph-input_to_dgraph-input-old'.
10-Jun-2015 06:08:36 com.endeca.soleng.eac.toolkit.script.Script runBeanShellScript
SEVERE: Utility 'move_dgraph-input_to_dgraph-input-old' failed.
With a bit of further digging I've found this error in a log file in the PlatformServices\workspace\logs\shell folder:
Failed to move D:\Firebird\config\script\..\..\.\data\dgraphs\Dgraph1\dgraph_input to
D:\Firebird\config\script\..\..\.\data\dgraphs\Dgraph1\dgraph_input_old: No such file or directory at -e line 1.
The state of the server is that is has a dgraph_input_new folder but it's struggling to create the dgraph_input_old folder. The dgraph_input folder does exist so the 'No such file or directory' is interesting.
The server has plenty of disk space for the operation and as it's intermittent I don't think it's file/folder permissions (otherwise it would fail all the time). I've even asked for on-access virus scanning to be disabled for those folders in case our virus scanner was locking files/folders.
I'm struggling to come up with a resolution to the issue, HALP!
EDIT: The forge process did stop the dgraph but the TomCat6 process is still running. Is that normal? Could TomCat be locking the folder?
EDIT: The task to move the folder is a bit of Perl that looks like this:
perl.exe -e "use strict; use File::Spec; use File::Copy; use File::Glob qw/:glob/;my $source = 'D:\Firebird\config\script\..\..\.\data\dgraphs\Dgraph1\dgraph_input'; $source =~ s/[\\\/]+$//;my #sources = bsd_glob($source); foreach my $file (#sources) {my #fromPath = File::Spec->splitdir($file); if (scalar #fromPath eq 0) { die \"Failed to split path: $!\"; } my $fromRelative = #fromPath[scalar #fromPath - 1];my $toFile = 'D:\Firebird\config\script\..\..\.\data\dgraphs\Dgraph1\dgraph_input_old'; if ( -d $toFile ) { $toFile =File::Spec->catdir($toFile, $fromRelative); } my $res = move($file, $toFile);if (! $res) { die \"Failed to move $file to$toFile: $!\"; }}"
EDIT: It seems to be a plain permission issue, I can't rename the folder without elevating myself to an administrator. The service is running as a user who's in the Administrators group.
What could happen to make this folder admin only?
I know this question is dated back 3 years ago. But recently i experienced the same issue, thought it could help others.
The logs were interesting as GogLlundain pointed out.
The way to solve this is.
Stop mdex server in the workbench which will in parallel kill
dgraph process too.
If you open the task manager in the server where mdex is defined, you can
find two dgraph.exe is running.
Kill the older task(i.e dgraph.exe) then run the baseline script, Your
process will run smoothly.

SSIS Execute Process Task Can't Find executable

I am using the 7zip standalone .exe to unzip a file. I am using the Execute Process task for this. I have tested this over and over again on multiple machines and I know it works (at least in debug mode/visual studio). I have uploaded this package the server. I have created a job that calls said package from the Package Store. The package is not able to find the .exe no matter where I put it.
My first thought was to put the .exe on the C:\ drive, which failed. I have also failed in my attempts to place the .exe on a network location that the account the package is running under has full control over.
Basically, has anybody else had issues getting the Execute Process Task to find an executable when the package is uploaded to the server?
The error message is
Can't find 7za.exe in directory C:\7zip
I'll risk a downvote for being wrong, but I believe you have a permission issue.
You say it runs fine on other servers from BIDS, try it without BIDS. Call it from a command-line on a box that it works on.
dtexec.exe /file C:\HereComesTheUnzipper.dtsx
If that works, then repeat the step on the troublesome server. RDC into the box and try again
dtexec.exe /ser localhost /sq HereComesTheUnzipper
If that still works, then you are looking at an issue with the job. What account is the SQL Agent service running as? Is the SSIS job step running as a particular set of credentials? If so, is it a SQL Server login (which wouldn't map to anything on the physical box)? Regardless of what your answer is, the resolution will be to ensure the account has access to
7z.exe
whatever scratch area 7zip may use while unpacking files (I assume %temp%)
the output folder (C:\bin\7z.exe -e e:\data\MyThing.7z)

RestartManager fails to restart application during update

I'm using c#, .net 4, WIX 3.5, Windows Vista.
I have made my application compatible with RestartManager by p/invoking the RegisterApplicationRestart method and by handling the WM_QUERYENDSESSION and WM_ENDSESSION window messages (I return new IntPtr(1);).
If I try to update my application manually, then everything works as it should:
Launch application;
Launch msi file containing new app version;
During the installation/update, I'm prompted to close the running application;
Upon continuing the running app is closed, install completes, and the app is restarted;
If I try to update my application from the application itself, then I run into problems:
1) Launch application;
2) Download the new msi file;
3) Launch msi file with:
using (System.Diagnostics.Process p = new System.Diagnostics.Process())
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "msiexec";
p.StartInfo.Arguments = "/i \"" + downloadPath + "\" /passive";
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = securePassword;
p.Start();
}
4) Because I'm using passive mode, the application is closed automatically;
5) After the installation, my application is not restarted and under Event Viewer I have an
Event 10007 - Application or service 'MyApp' could not be restarted.
I have tried:
Not to use passive mode for msiexec;
Launch msiexec via cmd.exe (cmd.exe /C "msiexec /i ....") - in the hopes that launching msiexec from another process would solve the problem;
Wait for 60+ seconds before launching the msi update (shouldn't be relevant in my scenario, but MSDN documentation has something about it...)
But none of the above has worked (always the same result).
Having to launch the setup with elevated permissions might have something to do with the issue, because during the manual update I get a warning in the Event Viewer - Application MyApp (pid 3220) cannot be restarted - Application SID does not match Conductor SID.
Despite this, restarting the app still works. Googleing the warning yields no good/specific results, only that this warning is probably caused by running the msi in an elevated prompt.
How do I fix (or workaround) this issue, so that I can update my application from the application itself and restart my application afterwards?
Edit - extra testing:
There doesn't seem to be a need to respond to WM_QUERYENDSESSION and WM_ENDSESSION messages, because application restart during a manual upgrade works without them, so we can rule them out;
If I don't provide administrator credentials to the application initiated upgrade and instead I type them in during the upgrade, then app restarting works;
If I run an elevated command prompt and initiate an application upgrade from there (manually), then app restarting still works;
In order for application upgrade to work at all under Standard user accounts (so far I tested under an Administrator account with UAC), then I also have to set p.StartInfo.LoadUserProfile = true;. Otherwise nothing happens. (application restart still doesn't work though);
I tried all other process StartInfo parameters that I could set - WorkingDirectory, Redirect, Verb
(= "runas") - no change in results;
I installed Vista SP2 onto the virtual machine that I have been testing on (so far ran SP1), but no change;
I performed an "automatic" application upgrade with verbose logging. In the end there was an error message - RESTART MANAGER: Failed while restarting applications. Error: 352. That error code is very generic (http://msdn.microsoft.com/cs-cz/library/aa373665), inorder to get more detailed info I would have to write my own installer that would call RmGetList after the error, then I might get more details (this though is something I'm not willing to do);
Edit 2 - msi log file:
http://mommi.planet.ee/muu/log.txt
Assuming that the manual process indeed works without any problem it seems that your need for Administrator privileges in combination with the "updating itself" leads to these problems. I see the following options:
create a batch file to execute the update
When you want to update call this batch file (with elevated privileges), make the app close itself... the batch file should wait some seconds, then check whether the app is still running (and close it in case) and then run the commandline you need to run msiexec - don't restart the app from within msiexec but after a successfull run of msiexec from the batch file.
create a batch file which is always used to start the app
When the time comes to update you just end the app. Either the batch file check for an available update and applies it, starting the app after successfull update OR the app set some environment variable which is then accordingly processed by the rest of the batch file.