Write a file to Roaming folder using NSIS script - c#

I am using NSIS to make exe for a desktop application in c# and i have to write few files to the AppData Roaming folder for the user
I tried the below code
!define ROAMING_FOLDER_ROOT "$APPDATA\APPDUMMY\APPFILES"
MessageBox MB_OK 'AppDATA FOLDER "${ROAMING_FOLDER_ROOT}"' #here i am getting the correct path of the Appdata roaming folder frm variable
Section -Additional
SetOutPath "$ROAMING_FOLDER_ROOT"
SetOverwrite off
File "C:\MYAPPSOURCECODE\BIN\BookStore.sqlite"
SetOverwrite ifnewer
File "C:\MYAPPSOURCECODE\BIN\AppSettings.xml"
File "C:\MYAPPSOURCECODE\BIN\Resources\defData.xml"
File "C:\MYAPPSOURCECODE\BIN\Resources\dummy.html"
SetOutPath "$ROAMING_FOLDER_ROOT\Resources"
File "C:\MYAPPSOURCECODE\BIN\Resources\appjsfile.js"
SectionEnd
While i am trying to do the same with $LocalAppData its writing to the AppDAta Local folder but i want to make it writable to Roaming folder

If you look at the code you posted you see that in the MessageBox call you referenced the ${ROAMING_FOLDER_ROOT} define but when calling SetOutPath you are referencing a variable called $ROAMING_FOLDER_ROOT and this probably produces a compiler warning. Make sure that you use the ${} syntax when accessing defines!
NSIS has a concept called the shell context and the $AppData constant is affected by this:
SetShellVarContext current ; Current is the default
DetailPrint AppData=$AppData ; C:\Users\%username%\AppData\Roaming
SetShellVarContext all
DetailPrint AppData=$AppData ; C:\ProgramData (This is in the All Users folder on XP)
SetShellVarContext current ; Restore it back to the default

Ah, seems,
you are using common shell context
Try to set
SetShellVarContext current
before you are getting $APPDATA.
Var ROAMING_FOLDER_ROOT
MessageBox MB_OK 'AppDATA FOLDER "${ROAMING_FOLDER_ROOT}"' #here i am getting the correct path of the Appdata roaming folder frm variable
Section -Additional
SetShellVarContext current
StrCpy $ROAMING_FOLDER_ROOT "$APPDATA\APPDUMMY\APPFILES"
SetOutPath "$ROAMING_FOLDER_ROOT"
SetOverwrite off
File "C:\MYAPPSOURCECODE\Models\BookStore.sqlite"
SetOverwrite ifnewer
File "C:\MYAPPSOURCECODE\BIN\AppSettings.xml"
File "C:\MYAPPSOURCECODE\BIN\Resources\defData.xml"
File "C:\MYAPPSOURCECODE\BIN\Resources\dummy.html"
SetOutPath "$ROAMING_FOLDER_ROOT\Resources"
File "C:\MYAPPSOURCECODE\BIN\Resources\appjsfile.js"
SectionEnd

Related

My program stop when it saves files on the directory (inside the app directory) after creating the setup by inno setup Compiler?

On my project I have instructions that save Excel Files in a folder called "Ficheirs" inside the Project bin\debug directory (bin\debug\fichiers) using: Directory.GetCurrentDirectory() + "\Fichiers" to set the path to that , it works well before creating the setup
However after creating the setup using inno Setup Compiler , and eventually adding the folder "Ficheirs" while creating the setup , my program doesn't work
How to fix that so that my program keeps saving my excel files on that folder ?
Directory.GetCurrentDirectory() + "\Fichiers"
This is a very unreliable function to set a path to a directory.
Without testing, the application can work in a different directory at the time you are asking for GetCurrentDirectory().
e.g the working directory of the setup / App at the moment you run GetCurrentDirectory()
App\
App\bin\
App\bin\debug\
GetCurrentDirectory()+ "\Fichiers" returns
D:\Programs\App\Fichiers
D:\Programs\App\bin\Fichiers
D:\Programs\App\bin\debug\Fichiers
You should force at install all needed Dirs
Here is an example of a [Dirs] section:
[Dirs]
Name: "{app}\bin"
Name: "{app}\bin\debug"
Name: "{app}\bin\debug\Fichiers"
inside C#
Test before writing
try
{
// Set the current directory.
string target = Application.StartupPath + "\\bin\\debug\\Fichiers";
if (!Directory.Exists(target))
{
Directory.CreateDirectory(target);
}
// Change the current directory.
Environment.CurrentDirectory = (target);
..............
Setup iss
[Code]
var
excelPath : String;
..............
excelPath := ExpandConstant('{app}\bin\debug\Fichiers');

File already exists exception file.copy

I am trying to copy a driver file from my application folder to driver folder in windows 7. But as I run this program File already exists exception has been occurred if I check at driver folder manually the file does not exists at all.
Program.sDriverPath = Path.Combine(Program.sStartUpPath, #"windows7\amd64\MyDriver.sys");
string sPath = sDriverPath;
string sDestPath = Path.Combine(Environment.ExpandEnvironmentVariables(#"%windir%\system32"), #"drivers\MyDriver.sys");
MessageBox.Show("Source " + sDriverPath);
File.Copy(sDriverPath, sDestPath);
If you want to overwrite an existing file you need to use the overload which has a boolean parameter:
public static void Copy(
string sourceFileName,
string destFileName,
bool overwrite)
and specify true for overwrite.
Now it is odd that you say the file doesn't exist in the destination at all - I think it must do, and you're not looking in the right place.
Try setting a breakpoint in your code immediately before you call File.Copy() and check the sDestPath parameter.
I suspect that what is happening is that the File System Redirector is silently redirecting your application to a different folder.
Try checking the folder %windir%\SysWOW64 instead.
Finally, note that the process's user must be running as an administrator to write files into that location.
Thanks #Matthew Watson I found the solution. FSRedirector is redirecting system32 folder to SysWow64 folder.Go to syswow64 folder then go to drives folder you will find your file there.

Selenium driver location search path

I'm trying to set up selenium tests in nCrunch which outputs the tests to its own temp folder.
I'm getting the following error when I create the driver (new PhantomJSDriver()):
OpenQA.Selenium.DriverServiceNotFoundException : The PhantomJS.exe file does not exist in the current directory or in a directory on the PATH environment variable.
However I have checked and PhantomJS.exe does exist in the current directory (\bin\debug).
I then tried using new PhantomJSDriver(".\\") which should be the current directory and that does work.
What is the "current directory" Selenium is referring to in this message?
Rather than assuming ".\\", get the current working working directory by Directory.GetCurrentDirectory or System.AppDomain.CurrentDomain.BaseDirectory . Take a look at Get current folder path.
new PhantomJSDriver() will use your bin folder
if PhantomJS.exe does not exist there, try to find where it's located and insert full path in constructor
new PhantomJSDriver("real_path_to_PhantomJS.exe")

What is the correct way to save and edit a file in C# while using an .nsi install script?

In my project, I have an xml file that stores a bunch of strings that the program reads and displays. What I want to happen is to build the program with the file, use the install script to create the installer (I already move all the .dll and .exe files to a bin folder for the script via post-build events) and then have the end user be able to access this file and have the program automatically load the file each time its run.
This is how I currently open the file. This looks in the debug folder but I want it to live in a persistent location.
XmlDocument doc = new XmlDocument();
doc.Load("PowerManagers.xml");
My .nsi file:
!define FullName "Power Manager Safety Testing"
!define ProductName "Power Manager Safety Testing"
!define ProductExe "PowerManagerSafetyTesting.exe"
;--------------------------------
;Include Modern UI
!include "MUI.nsh"
!include "Framework .Net Install.nsh"
!include "Common Functions.nsh"
!include "Common Drivers.nsh"
ShowInstDetails show
!insertmacro Insert_System_Configuration
;--------------------------------
; The stuff to install
Section "${ProductName}" Sec_Id_Main
SectionIn RO
Call MainSectionInstall
; The files to use in this installer
File "..\..\bin\PowerManagerSafetyTesting\*.exe"
File "..\..\bin\PowerManagerSafetyTesting\*.dll"
File "..\..\bin\PowerManagerSafetyTesting\PowerManagers.xml"
SectionEnd
;---------
;---------
; Optional section (can be disabled by the user)
Section "Start Menu Shortcuts" Sec_Id_Start
Call StartMenuSection
SectionEnd
;---------
; Optional section (can be disabled by the user)
Section "Desktop Shortcuts" Sec_Id_Desktop
Call DesktopShortcutsSection
SectionEnd
;--------------------------------
; Uninstaller
Section "Uninstall"
Call un.UninstallerSection
SectionEnd
;--------------------------------
; Page descriptions
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SECDOTNET_ID} $(DESC_LONGDOTNET)
!insertmacro MUI_DESCRIPTION_TEXT ${Sec_Id_Main} "Installs the core files required to run the ${ProductName}"
!insertmacro MUI_DESCRIPTION_TEXT ${Sec_Id_Start} "Installs short cuts to the start menu"
!insertmacro MUI_DESCRIPTION_TEXT ${Sec_Id_Desktop} "Installs short cuts to the desktop"
!insertmacro MUI_FUNCTION_DESCRIPTION_END
You need to put your XML file inside Windows data directory i.e. C:\ProgramData\Your_App and read from there inside your C# app and write the file in that path from your installer.
C# program
String strPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
strPath += "\\Your_App\\PowerManagers.xml";
XmlDocument doc = new XmlDocument();
doc.Load(strPath);
NSIS script
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Explorer\ShellFolders" "Common AppData"
CreateDirectory "$0\Your_App"
SetOutPath "$0\Your_App"
File "..\..\bin\PowerManagerSafetyTesting\PowerManagers.xml"

How to change permissions of a folder inside System32 in C#?

I need to programmatically remove "create file" and "create directory" permissions on a directory inside System32 directory for a group "NT AUTHORITY\\INTERACTIVE".
To do this, I wrote following code:
string windir = Environment.GetEnvironmentVariable("systemroot");
string redirectionFolder = (windir + "\\System32\\Tasks2");
MessageBox.Show(redirectionFolder);
FileSystemAccessRule Tasks = new FileSystemAccessRule("NT AUTHORITY\\INTERACTIVE", FileSystemRights.CreateDirectories | FileSystemRights.CreateFiles, AccessControlType.Deny );
DirectorySecurity dirSecurity = new DirectorySecurity(redirectionFolder, AccessControlSections.Group);
dirSecurity.AddAccessRule(Tasks);
Directory.SetAccessControl(redirectionFolder, dirSecurity);
When I run this code on a folder C:\Tasks2, it works.
But when I run it on C:\Windows\System32\Tasks2, I get the System.IO.DirectoryNotFoundException exception. Running the app as administrator doesn't help.
What can I do in order to change permissions of a directory inside System32 directory in C#?
Assuming that C:\Windows\System32\Tasks2 really does exist, the most likely explanation is that you are being caught out by the file system redirector. You have a 32 bit process and the file system redirector converts system32 into SysWOW64. And so whilst you think you are looking for C:\Windows\System32\Tasks2, you are actually looking in C:\Windows\SysWOW64\Tasks2.
Compile your program as 64 bit. Or use C:\WINDOWS\SysNative.

Categories