Installer Custom action not working - c#

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"

Related

Azure function suddenly stopped working on Azure with no reason why

I am doing simple telegram echo bot on azure, which write telegramid of user to sql database.
I think i don't need to show code, but i can share with code to you if you require me to do this. I will explain by text.
I have function telegrambot which get response from telegram servers and send it to my UpdateService written by me where messages analyze and if message type is text i will write senders Id to my database.
Firstly i decide to just implement simple echo bot without database.
In startup file i write the next code
[assembly: FunctionsStartup(typeof(MyTelegramBot.Startup))]
namespace MyTelegramBot
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<UpdateService>();
builder.Services.AddLogging();
}
}
}
And i deploy it to Azure. Everything works fine, every message correctly come back to me.
Next i decide to Add database related files: entities, dbcontext
I have one table user and thats all.
Write operations was hold by IDbSaver
namespace MyTelegramBot.Interfaces
{
public interface IDbSaver<T> where T : class
{
Task<AlertMessage> RegisterUser(T entity);
}
}
Implementation of IDbSaver
namespace MyTelegramBot.Services
{
public class DbSaver<T> : IDbSaver<T> where T : class
{
protected DbSet<T> Dbset;
private readonly MyContext _context;
public DbSaver(MyContext context)
{
Dbset = context.Set<T>();
_context = context;
}
public async Task<AlertMessage> RegisterUser(T entity)
{
await Dbset.AddAsync(entity);
try
{
await _context.SaveChangesAsync();
return new AlertMessage()
{
Message = "Success."
};
}
catch(DbUpdateException ex) when(ex.InnerException is SqlException e)
{
if(e.Number == 2601)
{
return new AlertMessage()
{
Message = "Someone(maybe you?) registered same nickname."
};
}
return new AlertMessage()
{
Message = "some text"
};
}
}
}
}
Registered IDbSaver and Dbsaver in startup like
[assembly: FunctionsStartup(typeof(MyTelegramBot.Startup))]
namespace MyTelegramBot
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<UpdateService>();
builder.Services.AddLogging();
var connectionString = "connectionstring";
builder.Services.AddDbContext<MyContext>(s => s.UseSqlServer(connectionString));
builder.Services.AddScoped(typeof(IDbSaver<>), typeof(DbSaver<>));
}
}
}
And when i deploy it to Azure, deployment process goes well, no errors during publishing it to azure, but in Azure page of my function Alerting message is
MyTelegramBot: Could not load file or assembly 'Microsoft.Extensions.Logging, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
In the nuget package menu i found that microsoft.extensions.logging with version 7 and installed it, deploy again but error message still alive.
Guys, can you please help me.
I have next installed packages:
Microsoft.Azure.Functions.Extensions(1.1.0)
Microsoft.EntityFrameworkCore(7.0.0)
Microsoft.EntityFrameworkCOre.SqlServer(7.0.0)
Microsoft.Extensions.Logging(7.0.0)
Microsoft.Net.Sdk.Function(4.1.1)
Telegram.Bot(18.0.0)
Using:
.net 6.0
functions version v4

Need to get current path of my created dll class library

I can't get the currently path of my created dll class library, which is loaded as an ActiveX in a ASP.NET web site.
I have tried several commands, but no success. For example, I tried to get current path in variable _path:
namespace WebScanControl {
[ApplicationControl(Width=640,Height=480)]
public sealed partial class ScanControl:ApplicationControl {
public ScanControl() {
InitializeComponent();
}
protected override void Construct(ReadOnlyCollection<object> args) {
try {
string _path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
} catch(Exception ex) {
MessageBox.Show(string.Format("{1}{0}{2}", Environment.NewLine, ex.Message, ex.StackTrace), ex.GetType().Name, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
base.Construct(args);
}
}
}
However, variable _path gets:
C:\Users\miyahira\AppDataLocalTemp\3f3574554-2ef8-e8r9-9c8b-e40561d03bb
Which is not its path.
The current path of my dll class library is:
F:\webapp\WebScan\Scan\
As you see, this class library is an ApplicationControl. Is that the reason why it's not possible to get its current path?
Your main problem is that you are thinking that the library will stay on the disk.
ASP.NET during the start up get's all the assemblies, and moves it to the temporary folder, where it can use them as it wants.
So the C:\Users\miyahira\AppDataLocalTemp\3f3574554-2ef8-e8r9-9c8b-e40561d03bb is a correct path.
How does your ActiveX component being add to the Application? And what is the location of the ASP.NET site? You can try to get the path from the HTTPContext.ApplicationInstance property, but can't say for sure will it work or not.

Prevent view caching in Nancy when using the Spark template engine

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);
}

how to deploy database

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
}

Getting Application path during the installation

I'm deploying an application and during the installation after the user chooses where to install the app, I want to get that path; I'm in a custom action already but i don't know how to get the application path where it's going to be installed !
It's Windows Forms and I'm developing using Visual studio 2010 "C#".
And I'm using the default deploying tool...
Any idea?
thanks in advance...
The class your custom action is in should inherit from System.Configuration.Installer.Installer. This has a parameter on it called Context which has a Parameters dictionary. The dictionary contains a number of useful variables about the install and you can add some.
Once you have added the custom installer to your install project in the Custom Actions pane. Select the Install action and set the CustomActionData property to:
/targetdir="[TARGETDIR]\"
Then you can access the path like this:
[RunInstaller(true)]
public partial class CustomInstaller : System.Configuration.Install.Installer
{
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
string path = this.Context.Parameters["targetdir"];
// Do something with path.
}
}
I know it's VB but This worked for me.
Private Sub DBInstaller_AfterInstall(ByVal sender As Object, ByVal e As System.Configuration.Install.InstallEventArgs) Handles Me.AfterInstall
MessageBox.Show(Context.Parameters("assemblypath"))
End Sub
Sorry to post answer for old post but my answer may help other.
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (rkApp.GetValue("MyApp") == null)
{
rkApp.SetValue("MyApp", this.Context.Parameters["assemblypath"]);
}
else
{
if (rkApp.GetValue("MyApp").ToString() != this.Context.Parameters["assemblypath"])
{
rkApp.SetValue("MyApp", this.Context.Parameters["assemblypath"]);
}
}
}
public override void Uninstall(System.Collections.IDictionary savedState)
{
base.Uninstall(savedState);
rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (rkApp.GetValue("MyApp") != null)
{
rkApp.DeleteValue("MyApp", false);
}
}
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

Categories

Resources