In ASP.NET vNext, why is code not recompiled on the fly? - c#

I am running the HelloMvc sample application from the command line using k web. I have tried to run it using the different environments available to me using kvm use -runtime. When I change the controller and hit F5 (or Ctrl+F5) in the browser, the code is not recompiled automatically and the page does not change. What am I doing wrong?
Active Version Runtime Architecture
------ ------- ------- ------------
1.0.0-alpha3 svr50 x86
1.0.0-alpha3 svrc50 x86
1.0.0-alpha4 CLR x86
* 1.0.0-alpha4 CoreCLR x86

Running dnx web from your command line only starts your host. To get the automatic recompilation goodness something needs to watch the files for changes and restart your host if any changes are detected. To accomplish this use the --watch flag and run your web command like this:
dnx --watch web
Currently this just shuts down your host when a change is detected, so you need something that restarts it once that happens. IISExpress does this for you if you run your project from Visual Studio 14.
Your best bet for this workflow outside of Visual Studio is through a JavaScript build tool or npm scripts. I would recommend you to look into this gulp-aspnet-k plugin (note this plugin only works on windows currently) if you want continuous recompilation on file changes while working outside of VS14. Seems to be the best way to accomplish that without IISExpress that I have found. This plugin is/was windows specific, but looking at the code should get you started. :)
Glenn F. Henriksen has written a wrapper for nodemon that is very nice, called kmon. Try that out as well. The kmon GitHub repository has all the instructions you need

Based on the gulp plugin linked to by AndersNS, there's a bit of powershell you can use to automatically restart the application:
#powershell -NoProfile -ExecutionPolicy unrestricted -Command "for(;;) { Write-Output \"Starting...\"; k --watch web }"
If you stick this into a batch file (e.g. run.cmd) you can easily start the application, keep it running and automatically restart and rebuild on file changes.
Make sure you adjust the k command line if you want to use another target than web.

Related

Running and debugging Powershell modules in Visual Studio 2017

I'm developing a Powershell module in C#, in Visual Studio 2017.
I am a bit surprised that the developing-experience is so bad in terms of running and debugging so I'm trying my luck here.
The way it works for me now is as follows:
Implement the module
Compile
Start a new Powershell window
Navigate to the bin/debug folder
import the compiled DLL (import-module)
Run the commands
Close the Powershell window (as otherwise I cannot rebuild the project as the DLL file is locked)
Fix bugs, and go back to step #2
In case I need to debug the code, I use VS2017 attach to process and debug the code (after step #5).
That is not ideal in terms of DX and I would like to have something better, as close as to this:
Implement the module
Compile
Press F5 (start)
Powershell window opens up with the module loaded
Run the commands
Breakpoints hit pause the program like we used to
How do I achieve that?
I managed to get this work with help of above comment from #Glenn:
Start your debugging with external program
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
and the parameter line
-NoExit -command "Import-Module '<path to your module>'; "
With this you can now start with F5 -> get a powershell window with your already loaded module and the Debugger is attached to this process.
But you have to be careful if your binary module is written to target .NET Standard. In this case it seems that the debugger (VS2017 15.8.9) is not able to detect which run-time modules to load. So no breakpoints hit at all in this scenario! My quick workaround here was to add another project with Console App targeting .NET framework 4.xy and use this other project as start project with above settings. Now my workflow exactly mirrors your second sequence (1-6). Unloading the dll is no issue because stop debugging does end the process.

Can't build my service : Unable to copy file because it is being used by another process

I build a windows service in c# .net. I added Pre-Build and Post-Build event to automatically deploy my service on the build. But sometime I got this error :
Unable to copy file "[CompletPath...]\bin\Debug\Business.Data.dll" to
"bin\Debug\Business.Data.dll". The process cannot access the file
'bin\Debug\Business.Data.dll' because it is being used by another
process.
In the Pre-Build event i'm closing the service, killing all task that using file in the Debug directory and uninstalling the service. There is the code in the .bat that i'm running in the Pre-Build event :
SET executionPath=%~dp0
SET serviceName=%1
SET frameworkPath=%2
SET targetServicePath=%3
SET targetBinPath=%~4
set targetBinPath=%targetBinPath:~0,-2%
net stop %serviceName%
powershell -NonInteractive -executionpolicy Unrestricted -file "%executionPath%\unlockfiles.ps1" "%targetBinPath%"
%frameworkPath%\installutil.exe /u %targetServicePath%
Exit /b 0
On the post-build event i'm installing and starting the service, there is the code even if this is not the problem because i'm gettring the error on the build, so the post-build event is not executing.
SET serviceName=%1
SET frameworkPath=%2
SET targetServicePath=%3
%frameworkPath%\installutil.exe /ShowCallStack %targetServicePath%
net start %serviceName%
I'm not always having the problem. I usually have the problem the first time i'm building, i'm cleaning the solution, build again and usually it's working after this.
I would separate these processes if I were you. You don't need to uninstall the service in order to update the files.
I'm not a great fan of pre/post build events for much more than moving some files around after the build has completed.
I use xcopy /y /c "$(TargetPath)" "location to copy to"
If memory serves I didn't even actually have to stop the service in order to update the dlls, however you may need to just stop the service in the post build before doing the xcopy commands.
If I were in your situation I would start to employ and more team oriented solution.
I would spend some time setting up a Continuous Integration system using something like Team City (this tool is free for upto 20 build configurations. I REALLY rate everything from JetBrains.
Then each time one of your team checks in new source code for the service it will be detected automatically by the build system (Team City) and a new set of builds will be triggered.
You could have a debug build that runs your unit tests against the code, a release build that also then includes a WiX Project that also then builds an installer for the service.
Once those processes are completed you can configure it to pop the installer in a known location on your network and it can also then email all the developers in your team to notify them that a new version of the service is available for installation.
WiX is a VERY mature installation authoring tool that is used by Microsoft for a lot of their products. There is a lot of support out there for the tool set and will make your entire process much tighter, repeatable and predictable.
It will take some time to get all of this completed but it really is worth the effort.

Powershell script works in one .NET Solution, not another

I am using a C# library I found that runs some remote Powershell scripts for Outlook Live. As a proof-of-concept that it works, I made a unit test that I can run (and step through for debugging) which merely calls a public static method inside this library which behind the scenes opens a remote Powershell session and runs a script.
This works just great in one of our Solutions, but it does not work when I run it in another Solution, even though both Solutions have the same two projects and test classes in them.. One Solution gives me an exception
There were errors in loading the format data file:
Microsoft.PowerShell, , C:\Users\xxxx.xxxx\AppData\Local\Temp\tmp_8c84e626-4399-420b-b874-9feeb3b1e195_tjlxhzzr.rlr\tmp_8c84e626-4399-420b-b874-9feeb3b1e195_tjlxhzzr.rlr.format.ps1xml : File skipped because of the following validation exception: File C:\Users\xxxx.xxxx\AppData\Local\Temp\tmp_8c84e626-4399-420b-b874-9feeb3b1e195_tjlxhzzr.rlr\tmp_8c84e626-4399-420b-b874-9feeb3b1e195_tjlxhzzr.rlr.format.ps1xml cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details..
One attempt I made was to modify the PSCommand inside the C# library to have Unrestricted set and that did not solve the problem. However, if I open up the x86 Powershell and run set-executionpolicy Unrestricted my test will run in both Solutions. Changing the execution policy in the x64 version of Powershell had no effect on either Solution.
Is there some type of setting for permissions that is specific to a Solution? Neither the Web.Config or Global.asax should matter since I'm not loading any pages, so I don't know what else would take effect since I'm running the same unit test in both solutions with the same test runner (Testdriven.Net).
Any ideas? Thanks.
Run as administrator usually sets hklm otherwise it is set in hkcu
on a 64bit OS you need to run Set-ExecutionPolicy for 32bit and 64bit PSH separately
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
to check
cd "hklm:\Software\Microsoft\Powershell\1\ShellIds\Microsoft Powershell"
dir

EAZfuscator not working automatically

I have a C# 2010 WinForms application using .Net Framework 4.
I am using Eazfuscator.NET to obfuscate this application. If I obfuscate the executable manually, everything works fine.
When I try to make the program obfuscate itself on every build by dragging the project onto the green part, everything works fine and this is output:
Protecting project 'Roster Manager.csproj'... done
Protected project will be obfuscated automatically during the build in Release configuration
Please restart Visual Studio to complete the installation of Eazfuscator.NET
After that, I close VS, start it again, clean the solution, rebuild it and run it. The program works but it is not obfuscated, as proved by decompiling it using Reflector 7.
I am building it in Release as requested by the program.
Searching the web didn't help so maybe if someone ran into this problem before might have a fix to this issue.
Eazfuscator add this line to the PostBuildEvent (Word Wrapped for legibility, but it is one line) of your project. (Right click on Project -> Properties -> Build Events.)
if /I "$(ConfigurationName)" == "Release" Eazfuscator.NET.exe "$(TargetPath)"
--msbuild-project-path "$(ProjectPath)" --msbuild-project-configuration "$(ConfigurationName)"
--msbuild-project-platform "$(PlatformName)" --msbuild-solution-path
"$(SolutionPath)" -n --newline-flush -v 3.2
Check if it is present and if your release configuration is really called "Release".
Finally managed to fix it. Seems that disabling the User Account Control resolves the issue.
A quick Google search will give more details into how to do this.
If you're using a version control system like TFS, .csproj file may be locked.
So you'll have to unlock file by checking it out or unchecking "Read-only" box from file properties.

What's the best way to deploy an executable process on a web server?

The original question:
The title of this question might be a bit clumsily phrased, but here's the situation:
I have a .NET web project deployed on my server. It's still in beta, so there's a lot of releasing and re-releasing happening.
I have also written a C# executable in the same VS solution (call it "admin.exe") that runs in the background on the server, periodically performing certain business rule integrity checks and making appropriate insertions to a warning table in the DB.
Question is: what's the best way to deploy this app so that it gets updated whenever I make a new release? It should be running all the time in between releases, so ideally I'd like some sort of setup whereby the shutdown-deploy-startup process involves the minimum possible number of steps.
Thanks!
Edit - Bounty started
The answers given thus far have been helpful and interesting, but haven't provided me with a clear, concise and elegant solution. Please do not assume I have extensive knowledge of deployment projects, because I don't. Bounty goes to the person who can provide a solution that does the following:
Publish the latest version of the web site;
Shut down any instances of admin.exe that are running on the server;
Update admin.exe;
Launch admin.exe;
All of the above should be done preferably in one step, or as few steps as possible, seeing as it will be done repeatedly throughout the life of the product; and
All of the above should be done preferably without requiring installation of any 3rd party software.
Thank you for your help!
Minor edit - clarification
I think a lot of the solutions offered thus far have overestimated the complexity of the problem, so let me clarify: everything that is to be deployed, only has to be deployed on one computer, which also happily has Visual Studio available with all source code. I only need to (1) publish the web site to the web folder, and (2) shut down, reinstall and restart admin.exe on the same server. Isn't there a simple way of doing this in one step? Can it be done with a VS Deployment project?
The "correct" way is probably to set up deployment scripts and installers, but being able to just click publish in Visual Studio and skip going in with remote desktop is a lot more convenient during development.
I have an admin web app that acts as a front end to a command line app - slightly different from what you are doing, but the same solution should work.
Simply add a reference to the console project in the admin web app. Even though you don't call any methods in the console project, the reference will cause the console app to be rebuilt and uploaded when you publish the admin website.
A simple start/stop page added to the web app takes care of steps 2 & 4 - Mine calls Process.Start()/Process.Kill(), though you obviously have the option of a cleaner shutdown depending on the setup of admin.exe.
Below is the code from my start/stop page - I have them set up as web service methods (to facilitate some monitoring stuff you probably won't need), but they should work just as well called from a simple button click method. Note that the service account will need permission to run/stop the process - on a dev box the simplest option is to set up iis to run as an admin user rather than the default service account.
private void KillProcess(string name)
{
var binpath = Server.MapPath("~/bin");
var pp2 = Process.GetProcesses();
var pp = from p in pp2 where p.ProcessName.Contains(name) && !p.ProcessName.Contains("vshost") select p;
foreach (var p in pp)
{
p.Kill();
}
}
[WebMethod]
public void StartQueueRunner()
{
var binpath = Server.MapPath("~/bin");
System.Diagnostics.Process.Start(Path.Combine(binpath, "TwoNeeds.QueueRunner.exe"));
}
[WebMethod]
public void StartQueueRunner()
{
var binpath = Server.MapPath("~/bin");
System.Diagnostics.Process.Start(Path.Combine(binpath, "TwoNeeds.QueueRunner.exe"));
}
It sounds like you need to take a look at a custom MSBuild script for deployment.
MSBuild does much more than just build solutions. You can also use it to copy files and update them, too. A good resource for tasks to do this is the MSBuild Community Tasks here.
You can then include the deployment of your background process alongside the deployment of the Web site deployment.
An alternative approach might be to use Windows Powershell with something like PSExec to remotely execute copy and update commands.
Both these kinds of approach can be automated very well with continuous integration servers such as Hudson. I have a build process that automatically monitors my source code repository, builds the program, deploys to a staging server, runs acceptance tests, then deploys to a preview box. I have another (manual) job that with one click deploys this preview version to live, minimising downtime and (usually) reducing errors from mistiped commands.
There is probably a much cleaner way but maybe install it as a windows service then script the install / uninstall commands using installutil.exe. Then just update the folder where the service sits and re-run the script for each update?
Great service tutorial here
Hope this helps
I would recommend writing a script that you could run on your PC, that would do the deployment over the network (so that you don't have to log in to the target machine every time). I have done it using msbuild, but you can really just go for a batch file.
I assume your admin process is running a windows service (anyway, it makes sense to run it as a service), so you would deploy it like this (this is part of the msbuild script - you can delete the bits with username and password if you don't need it):
<ItemGroup>
<ReleaseFiles Include="localPath\bin\*.dll"/>
<ReleaseFiles Include="localPath\bin\*.exe"/>
<ReleaseFiles Include="localPath\bin\*.pdb"/>
<ReleaseFiles Include="localPath\bin\*.config"/>
</ItemGroup>
<Target Name="Release">
<Message Text="Installing Admin on $(DeploymentMachine) as user $(User)"/>
<Exec ContinueOnError="true" Command="sc.exe \\$(DeploymentMachine) stop "Admin"" />
<Exec ContinueOnError="true" Command="sc.exe \\$(DeploymentMachine) delete "Admin"" />
<Delete ContinueOnError="true" Files="\\$(DeploymentMachine)\C$\path-to-admin\*.*"/>
<MakeDir Directories="\\$(DeploymentMachine)\C$\path-to-admin"/>
<Copy SourceFiles="#(ReleaseFiles)" DestinationFiles="#(ReleaseFiles->'\\$(DeploymentMachine)\C$\path-to-admin\%(RecursiveDir)%(Filename)%(Extension)')" />
<Exec Command="sc.exe \\$(DeploymentMachine) create "Admin" binpath= "C:\path-to-admin\admin.exe" start= auto obj= $(User) password= $(Password)" />
<Exec ContinueOnError="true" Command="sc.exe \\$(DeploymentMachine) start "Admin"" />
</Target>
Deploying IIS web sites is usually a bit more pain, but if you have everything set up on the target machine then possibly it would work to just copy the files over the network (again using the \DeploymentMachine\share or \DeploymentMachine\C$\path addressing).
Unfortunately deployment is never nice nor elegant :(
Please let me know if you need clarification on anything
Here's a nasty thought. If you're admin.exe isn't doing anything too hard core, why not throw into IIS? To write a C# Web Service, you probably won't need to change much.
To ensure it gets called repeatedly, you could use any variety of methods, like Windows Scheduler to run wget once a minute. Keep concurrent copies from running with a file lock, should it ever take MORE than one minute to complete.
This would make your deployment as simple as a file copy (FTP). I don't even think you need to reboot IIS when pushing a C# DLL. If you do, you can script that up over SSH.
To me, your problem sounds a lot like the deployment problem SharePoint solves through their Timer service running in each WFE, stsadm enqueuing admin tasks, that service dequeuing and running them etc.
What I would do is to
write a service running in each WFE
write a small custom "stsadm" tool so you can enqueue tasks, specify when they need to run, etc.
Another approach: what about using the plain vanilla Windows Task Scheduler? Look here, you can easily enqueue tasks remotely for ex.
I would write a command-line application that would do all of that.
Here is a rough example:
Site.api.publish();
admin.api.shutdown();
while(shell.status("admin.exe") == true) {}; //still running
file.replace("admin.exe", "path-to-compile\admin.exe");
shell.run("admin.exe");
You probably get the point. If you want it to do it automatically just use the Task Schedular to call it every day, or however often you want it.
Store on the server/web the most recent version of the project that is online. eg: in a version.txt the value "2.1.0", or query the database if you have access too.
Your application running on clients, will periodically read the contents of the version.txt file, then compared against the inbuilt(self) version number.
If a patch or minor release is detected eg 2.1.123, spins out a second app(updater.exe) that will quietly
do the upgrade,
it shall download the updated(preferred zipped) project from server/web.
Stop any running instances.
Unzipping the content.
Backup existing files(rename)
copy/install the new version of the project,
Start the application (when the app is restarted successfully it will delete its own backup file).
if a major release is detected eg: 3.0.0
notifies the user there is a major upgrade
if user accepts, download the installer
runs a full installer update
Does this help?
VS Deployment project for a web app is not that easy to master and somewhat not reliable. What I'd suggest:
Modify your Admin.exe into a .NET Windows service. Seebelow why would you need to do it.
Use sc.exe, InstallUtil.exe or installer-building services like installer.codeeffects.com to reinstall your service fast on every deployment. Btw, if I remember correctly, at installer.codeeffects.com you can download a VS example code of how to build a .NET Windows service if you're new to services.
Deployment could be done like this (assuming that your needs in automation is minimal and you're fine deploying almost manually):
Run either of the above mentioned tools to reinstall your service first. The sc.exe and InstalUtil.exe tools support command line. Therefore, if your web app, VS and the service is running on the same machine (your development computer, I assume?), you can right-click the web project in VS, select Properties and set pre- or post-build commands in the Build Events tab there. This way your VS can automatically rebuild and reinstall your service before you publish your web app. This is the main reason why the exe program is not good in your case, a Windows service would serve you better.
Then deploy your web app (assuming it's been build as discussed above). No biggies here, just use the Publish command from your VS or move all files of your web app except for the .cs files, /Properties/ and /obj/ folders. Or, if running from the project's folder, just right click the main page and select "View in Browser" - this will start the run time through VS without starting the debugger.
Sorry for such a lengthy post. Did I understand your question and clarifications correctly? :)
What about making admin.exe a click once deployment. Then in your admin.exe, before you check the integrity of business rules, check if an update is available. If it is, update and then continue on with your checks.
In order to make things simple and make sure I would be able to roll back everything, I would create a PowerShell Script that performed the following actions:
Stop the Application Pool.
Copy the current web app to the
"history folder" so you can rollback
to that version if required
Deploy the new web app
Stop the current admin.exe from
services
Uninstall the admin.exe, by
executing the Uninstall.bat (this is
quite common for Windows Services)
Copy the current admin.exe app to
the history folder (see 2)
Copy the new admin.exe to the
correct location and run install.bat
Start the new service
Start the application Pool
You can automate all of that in a Powershell script (the only thing I'm not sure is about the app pool, but I'm pretty sure that you can do this).
More info on PowerShell can be found here: http://arstechnica.com/business/news/2005/10/msh.ars/2

Categories

Resources