Packaging an excel addin - c#

I have an automation addin for excel developed using C#. How do I package and distribute it ? Also when the addin is installed for the first time, I want a username and password check to pop for the first time.
How can I go about doing this ?
thanks

Visual Studio creates a setup project for each Add-in project. You could start by using that. It produces an MSI file that you can distribute.
About the second part - if you stay with Studio-generated setup you probably cannot add custom dialogs to installation. You'll need some tool that builds the installations.
How about asking for username and password on the first use? This way the installation remains simple. In my experience every question during installation increases the risk that the user says "WTF, why do I have to answer these stupid questions. Cancel".
To ask for username and password on the first use only you have to save them somewhere after asking, so that next time you know them. Approved Microsoft way is saving them in Settings. By default Studio creates Settings file in your peoject just for that. Just add two variables to that file with empty default values. Mark them as User variables (not the Application variables).
From your add-in, access them as Properties.Setings.VariableName.
When your add-in starts, check if you have the username and password in settings. If they are empty, ask and save.
if (string.IsNullOrEmpty(Properties.Settings.Default.UserName))
{
string name;
string password;
//ask for name and password, replace with your code
AskForUserandPassword(out name, out password);
Properties.Settings.Default.UserName=name;
Properties.Settings.Default.Password=password;
Properties.Settings.Default.Save()
}
Physically, this is saved somewhere deep in user directory in an XML file.

Related

Custom Actions Installer for Windows Service

I have a windows service which I silent install using msiexec.exe and I am passing the username and password for the "Set Service Login"
The Service is successfully installing but upon Starting the service I am receiving "error 1069: The service did not start due to logon problems"my logon account is administrator and I have tested that when I manually install using the same msi file and start the service it is starting successfully, I am stuck and need some ideas and guidance of what I am missing.
here is my overriden method from Installer Class.
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
var userName = Context.Parameters["USERNAME"];
var password = Context.Parameters["PASSWORD"];
if (!string.IsNullOrWhiteSpace(userName) && userName.ToLower() != "admin")
{
CustomInstallerParameters customParameters = new CustomInstallerParameters(Context);
SaveCustomParametersInStateSaverDictionary(stateSaver, customParameters);
}
else
{
Context.Parameters.Remove("USERNAME");
Context.Parameters.Remove("PASSWORD");
}
}
TIA.
It appears that you are using a Visual Studio setup project, and most likely also using one of the TextBoxes dialogs to collect the input.
You can't silently pass these parameters on the command line because Visual Studio generates custom actions to clear them (and I don't know why). In a silent install Windows runs just the InstallExecuteSequence, and if you look in there with (for example) Orca you'll see custom actions such as "CustomTextA_SetProperty_EDIT1" that clear the values. To state the obvious, the values you currently get will be blank, and you could verify this by logging the values somewhere.
So a starting point to getting this to work is to use Orca to delete those custom action calls in the InstallExecuteSequence table.
After that, there is a potential problem that the values won't make it to your custom action because they are not secured, so in the Property table you'd need to add those property names to the SecureCustomProperties list, semi-colon delimited (EDIT1;EDIT2 and so on).
Visual Studio setup projects aren't good at any of this, and something like WiX would be better because no code is required to install, start or stop services, or configure them with an account.
Most likely, different decade, same problem.... (SeServiceLogonRight)
http://iswix.com/2008/09/22/different-year-same-problem/
FWIW, I wasn't a big WiX user yet back then (I was merely dabbling at that point) but there are some real gems in the comments from my Matthew Rowan. He is correct... all of this gets WAY easier if you are using WiX.
For example you can follow this tutorial:
https://github.com/iswix-llc/iswix-tutorials
This creates a windows service running as SYSTEM. Add a reference to the WiXUtil extension and namespace and author a User element with the LogonAsService right set and your all set.
FWIW, my only concern with all this is that MSI needs property persistence if you don't want a repair to come by and corrupt the username and password. Property persistence is pretty easy to remember ( See: http://robmensching.com/blog/posts/2010/5/2/the-wix-toolsets-remember-property-pattern/ ) but the problem is providing enough encryption to not expose the account.
It's for the reason I typically suggest just running as NetworkService or SYSTEM and grant the computer object rights in a domain. An alternative is to have the installer create the service account and randomize the password on each repair so you don't have to persist it.

Visual Studio - Open program in current users files

So basically I'm using Visual Studio and I'm trying to get it so when the user clicks on a button, it opens a directory or program although I need it to detect the current user, so that it doesn't open my users files.
There are so many ways in .Net to get the current user. The most common answer you will find is String UserName = Environment.UserName;

Application Logic - Only allow one admin user to use app

I have a very tricky situation right now..
I have an application which downloads the email attachments of a particular email account, and then saves those attachment to a specified folder. The application also has some features, like sort the attachments by date, sort by keywords, etc.
So the app has two key features:
Email Attachment Download
Sorting
The requirement:
Only ONE administrator can run both features, and the normal users can only run the sorting feature
The Problem:
If there are two administrator accounts, how can I limit it to one only?
I only have one useful code as of now..
If My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
MsgBox("I have admin privileges")
Else
MsgBox("I do not have admin privileges")
End If
I just need to know if other admins are using the app. If one admin already ran the app, other admins can't run it anymore..only 1 instance of the app should run for all admins.. thanks.
Why not Create one application level variable to keep count
AdminLoggedinCount
default to 0 and +1 when app starts
If My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
If AdminLoggedinCount >=1
MsgBox("try again later another admin is using now")
Else
MsgBox("I have admin privileges")
End if
Else
MsgBox("I do not have admin privileges")
End If
You could do it by doing with a simple Semaphore file. The basic premise, when the application starts, and user is an admin user, try to open a file to a common location visible by all users. if the file exsits, try to erase it, in case the other user may have aborted out and did not properly close and erase the file.
If the file can not be deleted, then an admin is STILL active with the file open. When the user is finished, close and erase the file...
You could have a variable in the app for the status that the semaphore file is theirs (or not), and to allow (or not) the special extra feature.
Again, the file could be as simple as...
X:\YourSharePath\ActiveAdminUser.txt

Use Existing Lotus Notes 8.5 Security Session via .NET Application

I'm currently working on a .NET application that will be invoked from Lotus Notes 8.5. This .NET application is suppose to read some data from a Lotus Notes database, and export it to a file.
The code to connect to the Lotus Notes database is:
NotesSession ns = new NotesSession();
NotesView nv;
ns.Initialize("");
NotesDatabase nd = ns.GetDatabase("server", "file.nsf", false);
nv = nd.GetView("viewName");
Unfortunately, when ns.Initialize is invoked, the Lotus Notes component will prompt the user for their password. I understand that the method Initialize is overloaded, the user name and password can be provided. However, I will not know the username / password.
Since Lotus Notes will be open already, is there a way to access the Notes Database using the credentials of the user that is already logged into Lotus Notes? Essentially, I'd like to avoid having the user enter their Notes credentials again, but still access the database.
There is a setting that can be turned on in Notes in the User Security dialog. (You didn't mention the version of Lotus Notes. The dialog may be different if you're on an older version.) The setting is:
Don't prompt for a password from other Lotus Notes-based programs (reduces security).
Those last two words may be in parenthesis, but don't let that fool you. They are pretty important! The setting allows all programs running on that user's computer to use the Notes APIs without authentication. That opens the door for an email-borne piece of malware, amongst other threats. And never mind the fact that such threats have been rare in the Lotus Notes world. A big part of the reason for that is that keeping this setting disabled is the default.
From what I've said above, I'm sure you can understand why there isn't an easy way to do what you want to do!
The only way to disable the password prompt specifically for your application will be to use the Lotus Notes C API's feature set known as Extension Manager. I.e., you write a C source file that is compiled into a DLL. Your DLL must be installed on all users' machines, and an entry must be made in the notes.ini file in order to have it loaded when the Notes core DLLs run. The help files for the C API include some sample code showing how to do the Notes-specific part of this. You'd have to figure out the details of identifying the fact that it was invoked for your application, and (if I remember correctly) you would also have to write code to prompt the user for their password once and be responsible for securely storing it somewhere where your DLL can retrieve and decrypt it whenever it needs it.
I did find another way to perform this, without having to turn the "Don't prompt for a password from other Lotus Notes-based programs (reduces security)." check box on.
System.Type objNotesType = System.Type.GetTypeFromProgID("Notes.NotesSession");
dynamic ns = System.Activator.CreateInstance(objNotesType);
dynamic nd = ns.GetDatabase(AppSettings.NotesServer, AppSettings.NotesReplicaID);
if (nd.IsOpen != true) nd.OpenByReplicaID(nd.Server, AppSettings.NotesReplicaID);
dynamic nv = nd.GetView(AppSettings.NotesView);
I've tested it, and it works. I am not prompted for a password, and when accessing the Notes Database, I am accessing it under the current user's credentials. Also, no COM references needed to be added to the project.

.NET Publisher Certificates

I'm using a book for studying for .NET certification, and I'm stumped on the issue of publisher certificates.
Background:
Windows Vista Home Basic SP2
Visual Studio 2008
.NET 3.5 SP1
Goal:
Write a simple C# console application that has its permission to read from a specific text file determined by the application's certificate.
Symptoms:
I am able to read from the file despite assigning the Nothing permission set to the code group that is conditioned by the application's certificate.
Steps taken:
Wrote C# console application that uses StreamReader to read the file and output to the console. The application works as expected.
On the application's properties, I used the Signing tab, set ON the checkbox for "Sign the ClickOnce manifest", clicked the Create Test Certificate button, and entered passwords.
Next, I clicked the More Details button, navigated to the Details tab, selected the Public Key row, and clicked the Copy to File button.
In the Certificate Export Wizard, I chose not to export the private key, chose the DER encoded binary X.509 format, and provided the path of the .CER file.
Next I rebuilt the application.
I opened the .NET Framework 2.0 Configuration tool.
I navigated to My Computer > Runtime Security > Machine > Code Groups > All_Code
Right clicked All_Code, and selected New to begin the Create Code Group wizard.
Gave the new code group a name, then selected the Publisher condition type.
Clicked the Import from Certificate File button, then selected the newly created .CER file.
Next I selected the Nothing permission set.
When running the application, which should now be a member of the new code group, it still works the same. I would expect that if it's a member of the Nothing permission set that it couldn't read the file.
Thanks for any insight you can provide. I'm probably missing one little detail. I wonder if this has anything to do with using Vista Home Basic.
Can your application read the file in question w/o any certificate?
Adding Nothing to a set of existing permissions won't change much.

Categories

Resources