Hi what is the best way to deploy database script to my client pc? i have installed the app and have the sql management studio installed at my client pc. Everything went smooth except when i need to update the database. How do i update the database without having me to go to their pc to run the .sql update script. This question applies when my app is used at other country.
For updating code is fine as i am using the ClickOnce.
This is a window based app.
Please help
I would ship the SQL file with your application, and have application startup logic that always checks a certain location for scripts that need to be run. It could be as simple as checking a [application path]\MigrationScripts folder for all .sql files. If files are found, read in the contents and execute against the database.
Once the check (and potential database updates) are complete, continue loading the application.
Sample Code (untested), and a very basic implementation:
public class Migration
{
private string _migrationPath = #"C:\temp\MigrationSteps"; //change
private string[] _sqlFiles = null;
public Migration()
{
Initialize();
}
public Migration(string path)
{
_migrationPath = path;
Initialize();
}
private void Initialize()
{
_sqlFiles = Directory.GetFiles(_migrationPath, "*.sql");
}
public bool Run()
{
bool success = true;
foreach (string sqlFile in _sqlFiles)
{
ExecuteRun(File.ReadAllText(sqlFile));
}
return success; //Do something with this value
}
public bool CleanUp()
{
//Put some logic here to "clean up" files that have already been run.
throw new NotImplementedException();
}
private bool ExecuteRun(string sqlText)
{
//Call your data access library and execute the sqlText
throw new NotImplementedException();
}
}
Usage:
Migration migration = new Migration();
if (migration.Run())
{
migration.CleanUp();
}
else
{
//Do something
}
Related
Straight to the question:
How to make a simple .NET Core console application scriptable with Applescript?
For the sake of the experiment, let's assume that my app looks like below:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ScriptableCsharpApp
{
class Program
{
public static CancellationTokenSource CancellationTokenSource { get; set; }
= new CancellationTokenSource();
public static int StaticCounter { get; set; } = 0;
static void Main(string[] args)
{
Console.WriteLine("Running!");
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
CancellationTokenSource.Token.WaitHandle.WaitOne();
Console.WriteLine("Shutting Down!");
}
private static Response GetFullResponse()
{
return new Response()
{
Counter = StaticCounter++,
Message = "Hello from C#!"
};
}
private static string GetMessage()
{
StaticCounter++;
return "Hello from C#!";
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
CancellationTokenSource.Cancel();
}
}
public class Response
{
public int Counter { get; set; }
public string Message { get; set; }
}
}
Level 1: How do I make the following script return the Message from GetMessage(), while the app is running:
tell application "ScriptableCsharpApp"
set message to get message
return message
end tell
Level 2: How do I make the following script return the Message property of GetFullResponse's result, while the app is running:
tell application "ScriptableCsharpApp"
set response to get full response
set message to message of response
return message
end tell
EDIT
A comment claims that there's not enough info. I'm confused, but ok, let's be VERY verbose here:
on Windows, install .NET Core 3.x SDK
open Visual Studio 2019 on Windows
File -> New -> Project -> .NET Core Console app (C#)
copy-paste code from above over Program.cs
Ctrl+. to resolve missing references (should add a NuGet pkg for the threading stuff)
zip the solution folder, send it to a Mac, extract somewhere
on the Mac, install .NET Core 3.x runtime
in terminal.app, navigate to the solution folder and run "dotnet ScriptableCsharpApp"
Now you have a windowless app that runs until you (x) out of it.
The task is to explain what code changes are required so that I can open AppleScript editor, create a new AppleScript, copy-paste the script mentioned above and run it to get the desired results.
Enough detail?
I have ASP .Net MVC project with additional MFC Service running in it (.svc file included in project, not separate project). I name it Concentrator. It have static field bookDays that is being set from DB in static constructor. It's being used in GetSlots method of Concentrator. Here is code (I have removed everything unrelated)
class Concentrator : IConcentrator
{
private static int bookDays = 0;
public static int BookDays {
get { return bookDays; }
set { bookDays = value; }
}
static RegConcentratorGeneral()
{
var settings = //DB query was here
if (settings != null)
BookDays = settings.BookDays;
}
public getSlotsResponse getSlots(getSlotsRequest request)
{
DateTime dateStart = DateTime.Now.AddDays(BookDays);
}
}
I have also settings-saving Controller:
public ActionResult Save(ConcentratorSettings ConcentratorParams)
{
//Saving settings in DB removed
RegConcentrator.BookDays = ConcentratorParams.BookDays;
}
That was working on my PC, on test IIS server, but fails on production. getSlots simply uses old value of BookDays that being set in constructor. Seems like it doesn't change when I setting it using controller. There is no exception, Save() method ever saves settings in DB, but getSlots produces results based on prevevious value anyway. When I have replaced using BookDays by DB query in getSlots(), problem have disappeared. What could be the reason of that? Production server isn't cluster.
I am trying to remove some additional files under the user profile Local Application Data folder after the uninstall of the app.
i read about custom action, so i wrote this
namespace RemoveUserAppDataCA
{
[RunInstaller(true)]
public partial class Installer1 : System.Configuration.Install.Installer
{
public Installer1()
{
InitializeComponent();
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
// Very important! Removes all those nasty temp files.
DeleteUserDataProfile();
base.Dispose();
}
void DeleteUserDataProfile()
{
try
{
string path = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..\\MyCompanyFolder"));
if (Directory.Exists(path))
{
Directory.Delete(path,true);
}
}
catch (Exception)
{
throw;
}
}
}
}
I added the dll file to the project setup , then a added a custom actions , then under the uninstall , i added the ddl file of the RemoveUserAppDataCA . i built the system.
i did the installation , but when i uninstall the app the app folderthe user profile Local Application Data remains (does not get deleted).
What is wrong about the work ??
I found the problem , the folder path was wrong. The system was pointing at
"C:\Users\UserName\AppData\App_Folder" instead of "C:\Users\UserName\AppData\Local\App_Folder"
I'm using a self-hosted Nancy with Spark templates. I've disabled the cache specifically (though in DEBUG is should be disabled by default).
protected override void ApplicationStartup(Nancy.TinyIoc.TinyIoCContainer container, IPipelines pipelines)
{
base.ApplicationStartup(container, pipelines);
...
StaticConfiguration.Caching.EnableRuntimeViewDiscovery = true;
StaticConfiguration.Caching.EnableRuntimeViewUpdates = true;
}
However, making changes to the templates while the app is running doesn't seem to work, as the template changes are not picked up.
Is there anything else required to disable views caching?
Since you're application is self hosted, I'm guessing you've either overriden the view location convention to find views as embedded resources in your assembly or have configured your Visual Studio project to copy views into the output directory at compile time. In both cases your application is not running off the view files you have in the Visial Studio project, but rather off copies of them. In that case caching is not the issue.
Ok, managed to get this to work by adding a custom ViewCache in the bootstrapper:
public class MyBootstrapper : DefaultNancyBootstrapper
{
#if DEBUG
protected override IRootPathProvider RootPathProvider
{
get
{
// this sets the root folder to the VS project directory
// so that any template updates in VS will be picked up
return new MyPathProvider();
}
}
protected override NancyInternalConfiguration InternalConfiguration
{
get
{
return NancyInternalConfiguration.WithOverrides(
x =>
{ x.ViewCache = typeof(MyViewCache); });
}
}
#endif
The new ViewCache just reloads the template on every request:
public class MyViewCache : IViewCache
{
...
public TCompiledView GetOrAdd<TCompiledView>(
ViewLocationResult viewLocationResult, Func<ViewLocationResult, TCompiledView> valueFactory)
{
//if (viewLocationResult.IsStale())
// {
object old;
this.cache.TryRemove(viewLocationResult, out old);
// }
return (TCompiledView)this.cache.GetOrAdd(viewLocationResult, x => valueFactory(x));
}
}
Somehow the viewLocationResult.IsStale() was always returning false.
By default, this is an instance of FileSystemViewLocationResult which just compares the last update time of the view, but the timestamp this.lastUpdated was being updated before calling IsStale() from the DefaultViewCache, so the template was never removed from the cache
public override bool IsStale()
{
return this.lastUpdated != this.fileSystem.GetLastModified(this.fileName);
}
I'm trying to deploy a windows service but not quite sure how to do it right. I built it as a console app to start with, I've now turned it into a windows service project and just call my class from the OnStart method in the service.
I now need to install this on a server which doesn't have Visual Studio on it, which if I've understood it correctly means I can't use the InstallUtil.exe and have to create an installer class instead. Is this correct?
I did have a look at a previous question, Install a .NET windows service without InstallUtil.exe, but I just want to make sure I've understood it correctly.
If I create the class that question's accepted answer links to, what is the next step? Upload MyService.exe and MyService.exe.config to the server, double click the exe file and Bob's my uncle?
The service will only ever be installed on one server.
I know it is a very old question, but better update it with new information.
You can install service by using sc command:
InstallService.bat:
#echo OFF
echo Stopping old service version...
net stop "[YOUR SERVICE NAME]"
echo Uninstalling old service version...
sc delete "[YOUR SERVICE NAME]"
echo Installing service...
rem DO NOT remove the space after "binpath="!
sc create "[YOUR SERVICE NAME]" binpath= "[PATH_TO_YOUR_SERVICE_EXE]" start= auto
echo Starting server complete
pause
With SC, you can do a lot more things as well: uninstalling the old service (if you already installed it before), checking if service with same name exists... even set your service to autostart.
One of many references: creating a service with sc.exe; how to pass in context parameters
I have done by both this way & InstallUtil. Personally I feel that using SC is cleaner and better for your health.
You can still use installutil without visual studio, it is included with the .net framework
On your server, open a command prompt as administrator then:
CD C:\Windows\Microsoft.NET\Framework\v4.0.version (insert your version)
installutil "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)
To uninstall:
installutil /u "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)
The InstallUtil.exe tool is simply a wrapper around some reflection calls against the installer component(s) in your service. As such, it really doesn't do much but exercise the functionality these installer components provide. Marc Gravell's solution simply provides a means to do this from the command line so that you no longer have to rely on having InstallUtil.exe on the target machine.
Here's my step-by-step that based on Marc Gravell's solution.
How to make a .NET Windows Service start right after the installation?
This is a base service class (ServiceBase subclass) that can be subclassed to build a windows service that can be easily installed from the command line, without installutil.exe. This solution is derived from How to make a .NET Windows Service start right after the installation?, adding some code to get the service Type using the calling StackFrame
public abstract class InstallableServiceBase:ServiceBase
{
/// <summary>
/// returns Type of the calling service (subclass of InstallableServiceBase)
/// </summary>
/// <returns></returns>
protected static Type getMyType()
{
Type t = typeof(InstallableServiceBase);
MethodBase ret = MethodBase.GetCurrentMethod();
Type retType = null;
try
{
StackFrame[] frames = new StackTrace().GetFrames();
foreach (StackFrame x in frames)
{
ret = x.GetMethod();
Type t1 = ret.DeclaringType;
if (t1 != null && !t1.Equals(t) && !t1.IsSubclassOf(t))
{
break;
}
retType = t1;
}
}
catch
{
}
return retType;
}
/// <summary>
/// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase)
/// </summary>
/// <returns></returns>
protected static AssemblyInstaller GetInstaller()
{
Type t = getMyType();
AssemblyInstaller installer = new AssemblyInstaller(
t.Assembly, null);
installer.UseNewContext = true;
return installer;
}
private bool IsInstalled()
{
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
ServiceControllerStatus status = controller.Status;
}
catch
{
return false;
}
return true;
}
}
private bool IsRunning()
{
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
if (!this.IsInstalled()) return false;
return (controller.Status == ServiceControllerStatus.Running);
}
}
/// <summary>
/// protected method to be called by a public method within the real service
/// ie: in the real service
/// new internal void InstallService()
/// {
/// base.InstallService();
/// }
/// </summary>
protected void InstallService()
{
if (this.IsInstalled()) return;
try
{
using (AssemblyInstaller installer = GetInstaller())
{
IDictionary state = new Hashtable();
try
{
installer.Install(state);
installer.Commit(state);
}
catch
{
try
{
installer.Rollback(state);
}
catch { }
throw;
}
}
}
catch
{
throw;
}
}
/// <summary>
/// protected method to be called by a public method within the real service
/// ie: in the real service
/// new internal void UninstallService()
/// {
/// base.UninstallService();
/// }
/// </summary>
protected void UninstallService()
{
if (!this.IsInstalled()) return;
if (this.IsRunning()) {
this.StopService();
}
try
{
using (AssemblyInstaller installer = GetInstaller())
{
IDictionary state = new Hashtable();
try
{
installer.Uninstall(state);
}
catch
{
throw;
}
}
}
catch
{
throw;
}
}
private void StartService()
{
if (!this.IsInstalled()) return;
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
if (controller.Status != ServiceControllerStatus.Running)
{
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running,
TimeSpan.FromSeconds(10));
}
}
catch
{
throw;
}
}
}
private void StopService()
{
if (!this.IsInstalled()) return;
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
if (controller.Status != ServiceControllerStatus.Stopped)
{
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped,
TimeSpan.FromSeconds(10));
}
}
catch
{
throw;
}
}
}
}
All you have to do is to implement two public/internal methods in your real service:
new internal void InstallService()
{
base.InstallService();
}
new internal void UninstallService()
{
base.UninstallService();
}
and then call them when you want to install the service:
static void Main(string[] args)
{
if (Environment.UserInteractive)
{
MyService s1 = new MyService();
if (args.Length == 1)
{
switch (args[0])
{
case "-install":
s1.InstallService();
break;
case "-uninstall":
s1.UninstallService();
break;
default:
throw new NotImplementedException();
}
}
}
else {
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(MyService);
}
}
Why not just create a setup project? It's really easy.
Add a service installer to the service (you do it on the seemingly useless service "design" surface)
Create a setup project and add the Service output to the setup app folder
Most importantly add the Service project output to all the custom actions
Voila, and you're done.
See here for more:
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
There is also a way to prompt the user for credentials (or supply your own).
Topshelf is an OSS project which was started after this question was answered and it makes Windows service much, MUCH easier.I highly recommend looking into it.
http://topshelf-project.com/
Not double click, you run it with the correct command line parameters, so type something like MyService -i and then MyService -u to uninstall it`.
You could otherwise use sc.exe to install and uninstall it (or copy along InstallUtil.exe).
This Problem is due to Security, Better open Developer Command prompt for VS 2012 in RUN AS ADMINISTRATOR and install your Service, it fix your problem surely.