Read binary file from wix setup at installation step - c#

I`m having some trouble trying to modifying an sql script, marked in wix as Binary file.
Basically, what I want to do is read the file (binary file as it is declared), replace some values in it based on properties set in wix, and save the file, then run it as an sql script.
What I have tried so far: Getting the target directory with session.GetTargetPath("TARGETDIR"), but it returns me with wrong path, not the one where the script is initially extracted(such as a temporary folder) so i can modify it, then save it and make sure it will run the modified script.
My question is:
HOW can I get the path of a binary file at installation step, or how can I access it via session or w/e?
To mention: I have tried declaring it as a file, and later I can not run it as an sql script, cause it requires a binary, not a file.
Thanks!

You can use the formatted string format for entries in the file-table, i.e. [#filekey] to get the full path of the file. You should then be able to either set a property / CustomActionData-property and read it within a VBSScript.
Please note also the following (extract from the linked page):
The value of [#filekey] remains blank and is not replaced by a path until the installer runs the CostInitialize action, FileCost action, and CostFinalize action.

Related

Not overwriting saved xml files in C# Window Form

I am fairly new to C# and I was wondering how to keep an XML file from being overwritten if one already exists on the install. In the application, there are two files that contain info to connect to the Database. One of them is relatively dynamic, but the other is saved at the setup. If I do a publish and try to update the application it always overwrites both files. Any thoughts?
You can check if the file exists with File.Exists(Path)
You can look here for more information:
https://learn.microsoft.com/en-us/dotnet/api/system.io.file.exists?view=netcore-3.1
If this does not work you can try to read that file and if there is any data there just sont delete it.
I assume you are refering to configuration settings.
While designing your settings, in the designer, set scope to "User". This will bind the setting to the users local app settings, and will not be overwritten.
More info here: https://learn.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-create-a-new-setting-at-design-time

Prevent Spring connection file to be changed by users

I am working on an application with Spring.Net and Windows forms. I would like to prevent users to change the Spring configuration file, something like setting the configuration file as readonly. I read the Spring.Net documentation and I found nothing, I looked on visual studio's side but I did not find how to set a file as Readonly. The only thing I found is to encrypt the app.config file, it is working but it does not prevent user changes.
Do you have any idea?
Really preventing a change will be hard to impossible...
BUT usually it should be enough to be able to recognize whether it has been changed... to achieve this you basically need to implement some variation of the following scheme:
Create a hash of the file (together with a salt)
Store that value in your app.config
In your application read the file and recalculate that hash (with the same hash)
IF that value matches what is in your app.config all is fine, otherwise it has been changed and you need to take the appropriate action
To take the above a step further:
You could embed a copy of the file as an "embedded resource" into your application (EXE/DLL) and replace the file on disk on startup with the content of that resource - this way you make sure that the file is always what your application expects.
DISCLAIMER: the above scheme won't stop a really determined "attacker/hacker...".

initiating a string from a config file

I am asked to do this and I have no clue from where to start since I am new to it.
I have created a C# .NET application (a web api to be more precise) using Visual Studio 2012.
I created an lsi file ( the new version of msi files) to be able to deploy it on a server.
Now I want to create some sort of a configuration file where I can edit a string without having to go into the code every time to change it every time.
lets say the variable is called mystring:
1- how can I create a config file that request a string without having to go into the code?
2- how can I say the mystring=input string ?
I tried to look it up but since I don t have the exact name I don t really know what I am searching for ...
Thanks,
One solution would be to save a configuration file with the settings you want to load, I'd suggest saving it to the ProgramData folder.
I would save the settings to an XML file (or JSON) so you can serialize and deserialize the data into your program when it loads. Guide
You can also save other details so they'll persist each time the application is opened this way, such as a username field.

Using WritePrivateProfileString to write path issue

I am using WritePrivateProfileString in c# (through DllImport) to store paths taken from textboxes on the interface. And the .ini file name is hardcoded in my application
string ini_file = ".\\config.ini";
However, when the file writing happens, the configuration file is written to the first path taken from the interface instead of writing it to the exe directory. Which is quite odd.
Debugging shows that the values are sent correctly to the WritePrivateProfileString but it still is written to the wrong location. Anyone knows why is that happenening?
I'd guess that something is changing the working directory of your process, most likely your code in the process. Note that the documentation has this to say:
If the lpFileName parameter does not contain a full path and file name for the file, WritePrivateProfileString searches the Windows directory for the file. If the file does not exist, this function creates the file in the Windows directory.
Now my guess is that this applies if you supply just a file name. Because your file name starts with . I believe that will force the function to start from the current working directory.
Having said all of that, and no matter what the cause of the problem is, you should use a fully-qualified path in order to make sure the file is written where you want it to be written. Whenever you want the file to go in a specific directory, it's always easiest to force that by using fully-qualified paths.
You can find the path to your executable using Application.ExecutablePath and then remove the file name part.
Another point to make is that the same directory as the executable may be a bad choice. If your program is installed under the Program Files directory then the directory which contains the executable will not be generally writeable. I think you should consider using a directory under in the user profile. Look for one of the Environment.SpecialFolder values.
Further to David Heffernan's answer - you can use
Path.GetDirectoryName(Application.ExecutablePath);
to safely get just the running application's folder part.
If you're in a dll rather than an executable, you can use
Path.GetDirectoryName(Assembly.GetAssembly(typeof(MyClass)).CodeBase);
Both require System.IO, and were originally posted here. Second example also requires System.Reflection).
Application data files are supposed to be written to the LocalApplicationData special folder.
string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
You typically will not have permissions to write into the Program Files folder etc.

Make sure file got copied successfully using c#

I am creating an application to back up files from a source directory into a destination directory. I store the files information from the source and destination folders in separate lists then I compare the lists based on their size, date modified etc to see which files need to be copied.
Anyways the point is that I end up with a list of the files that need to be copied and I will like to know how much time is every file taking therefore I have tried the following techniques:
Technique 1
Technique 2
Thechnique 3 : the regular File.Copy("source....","Destination")
The first two techniques are great because I can see the progress. The problem is that when I copy some files with those techniques, the new file sometimes has different dates. I will like both files to have the same modified date and also the same creation date. Moreover if for whatever reason my program crashes the file that is being copied will be corrupted because I have tried copying a large file ( a file that takes about a minute to get copied in windows) if I exit my program meanwhile the file is being copied the file that is being copied sometimes has the same attributes and the same size so I want to make sure I don't have corrupted files in case my program crashes.
Maybe I should use aether techniques 1 or 2 and then at the end copy the attributes from the source file and assign those to the destination file. I don't know how to do that though.
FileInfo has members CreationTime and LastWriteTime that are settable - so you could settle for your preferring techniques and set the dates afterwards if that helps.
Have you considered just writing a shell script that calls robocopy? Any time I've had to run backup tasks like this, I just write a script -- robocopy already does the heavy lifting for me, so there's often no need to create a bespoke application.
A solution that I have but its long:
I know I can copy the file from the source and then name the file in the destination something else like "fileHasNotBeenCopiedYet" with attributes of hidden then when my program finishes copying the file change the name to the source name and copy the attributes and then latter I know that if a file with that name ("fileHasNotBeenCopiedYet") exists that means that the file is corrupted.

Categories