Why cannot libspotify save to cache? - c#

Running my C# application from Visual studio works fine (in this respect)
But when installing the application in my system (win7, .NET 4.0) I get problems with the cache.
These are the errors I get:
LogMessageCallback. Message:20:43:03.988 E [playlist:1978] Unable to save file: playlist.bnk
LogMessageCallback. Message:20:43:03.988 E [social-mgr:830] Unable to save file: social_stream.bnk
LogMessageCallback. Message:20:46:31.034 E [user_cache:107] Unable to save file: user-cache.bnk
LogMessageCallback. Message:20:43:04.988 I [c:/Users/spotify-buildagent/BuildAgent/work/1e0ce8a77adfb2dc/client/core/protocol/file_streamer_simple.cpp:769] Request for file 57a6ab34bad26645e2345a610ae652fe77f82afb complete (code: 0)
I have tried to deleted the entire cache library and it gets recreated when I start the app, so it can't be a matter of file privilege.
Since the cache does not seem to be valid my playlists are not accessible to me at startup.
I do log out properly.
Any explanation/workaround?

I think I've got it...
I search for the playlist.bnk file on my disk and found one under Spotify\bin\Debug\cache_location\Users\bes51659-user, that is from where I run my project with visual studio. "cache_location" in the path directed me to the settings_location argument in the config struct when creating the session. I had set it to const string "cache_location". I must have understood the explanation wrong:
https://developer.spotify.com/docs/libspotify/12.1.51/structsp__session__config.html#a342532432040d476aaaf73f10893d23b
The location where Spotify will write setting files and per-user cache items. This includes playlists, track metadata, etc. 'settings_location' may be the same path as 'cache_location'. 'settings_location' folder will not be created (unlike 'cache_location'), if you don't want to create the folder yourself, you can set 'settings_location' to 'cache_location'.
(a bit contradictory that the "cache_location" catalog was actually created under debug!)
The comment must mean that if I reuse the same location for setting_location as for cache_location I do not have to create it as it has already been created!
I do not know if libspotify did not have permissions to create the catalog "cache_location" under "program files", or if it expected it to be there and did not find it. But it does not matter. I have now changed both the locations to "c:\mySpotify" in the config struct and problem solved...
My only excuse is that google tells me that I'm not the first to have fallen into this pithole.

Related

Get access to program's own directory

this is a very simple issue.
Note: I am sure people have found and posted this same issue somewhere but I can't figure out the correct search terms to find it.
Okay, so here is my issue.
Let's say my program is stored at C:\Program Files (x86)\MyProgram\Program.exe.
Now in the program, it basically does
Directory.CreateDirectory(Application.StartUpPath + "\\Files")
So basically, this would create a directory called Files in the same folder as the program itself.
Assume that I have to create the folder in that location, so using a different location is not an option.
So the real problem is, if its located in the c:\Program Files directory, my program gets "access denied" when I try to create the folder.
So how can I get something like this to work without forcing the user to run it as an admin?
If it's in Windows 7, if UAC is elevate, you won't be able to modify anything in c:\Program Files without rooting yourself via 'run as administrator'.
And since windows is a multi-user operating system, storing anything user-specific there is a recipe for disaster.
The right place for your program to put its data is in the appropriate special folder, which you can get/create via either
// user-specific application data is stored here
string userSpecificAppDataDirectory = Environment.GetFolderPath(
SpecialFolder.ApplicationData ,
SpecialFolderOption.Create
) ;
// application data common to all users is stored here
string commonAppDataDirectory = Environment.GetFolderPath(
SpecialFolder.CommonApplicationData ,
SpecialFolderOption.Create
) ;
or one of the other Environment.GetFolderPath() overloads.
In modern operating system the folder C:\program files (x86) is write protected by the OS. You can't create sub folders here without using an administrative account (and also in that case you will be asked to confirm this action unless you disable UAC). So the correct way to follow is to create your data folder in another place. The best option is the CommonApplicationData folder extracted using:
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
or the SpecialFolder.ApplicationData enum if your data should be differentiated by the current user of the application, or the SpecialFolder.MyDocuments if these files are produced by your user and need to be opened freely by other programs (or need to be included in a backup)
After you get the special folder provided by the OS to store application data remember to create a subfolder for your application and the other subfolders as required by your requirements
// In Win7 this usually resolves to C:\ProgramData, but do not use this folder
string appCommon = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
// This resolves to C:\programdata\your_app_name\files
string appData = Path.Combine(appCommon, "your_app_name", "files");
// This will create all directories in the specified path one by one....
if(!Directory.Exists(appData)) Directory.CreateDirectory(appData);
You could try creating any files or folders you need during your installation procedure. I am not sure what success you would find if using a third party install creator, but my understanding is that items added via the Application Files... button in the Publish tab of the Project Properties section in Visual Studio then have access privileges kind of inherently granted for use by the application.

ClickOnce Application user settings locations

I am currently developing a ClickOnce application that converts CSV files for a database update. The program requires the user to have the ability to change the configuration files for a database change, and change an XML file which populates a drop-down list in the app.
Now I understand that the files are kept in the user/appdata folder to ensure there have the correct privileges, but do I have any influence as to what those folders are called, or where they are saved?
By default, the files are saved in AppData\Local\Apps\2.0\LD7ZEJK0.7AE\NJ42PEPW.1QX\csvt...exe_169e1a4011fbe7ec_0001.0000_none_04507fe9e077ae84
Can I change that to say Documents\CSV_Files or something similar? And if I do, how would I reference the XML file in the configuration file so the program knows where it is?
Normally, you shouldn't have to care about the location yourself. Just mark your XML file as data in the ClickOnce manifest and access it using the well-known:
ApplicationDeployment.CurrentDeployment.DataDirectory
Here's an MSDN article describing it: Accessing Local and Remote Data in ClickOnce Applications
I would never store any data that is important to be retained in the case of an update in the actual ClickOnce deployment directories -- it is too dangerous. You should copy those files out to ApplicationData and access them there. This article shows you how to do that.

Access to the path denied error in C#

I have read a similar post, but i just cant figure out the problem.
I have changed the windows permissions and changed routes.
When i try to save a file it throws me the exception:
Access to the path **** denied.
string route="D:\\";
FileStream fs = new FileStream(route, FileMode.Create); <--here is the problem
StreamWriter write = new StreamWriter(fs);
patient person = new patient();
patient.name = textBox1.Text;
patient.name2 = textBox2.Text;
You are trying to create a FileStream object for a directory (folder). Specify a file name (e.g. #"D:\test.txt") and the error will go away.
By the way, I would suggest that you use the StreamWriter constructor that takes an Encoding as its second parameter, because otherwise you might be in for an unpleasant surprise when trying to read the saved file later (using StreamReader).
Did you try specifing some file name?
eg:
string route="D:\\somefilename.txt";
tl;dr version: Make sure you are not trying to open a file marked in the file system as Read-Only in Read/Write mode.
I have come across this error in my travels trying to read in an XML file.
I have found that in some circumstances (detailed below) this error would be generated for a file even though the path and file name are correct.
File details:
The path and file name are valid, the file exists
Both the service account and the logged in user have Full Control permissions to the file and the full path
The file is marked as Read-Only
It is running on Windows Server 2008 R2
The path to the file was using local drive letters, not UNC path
When trying to read the file programmatically, the following behavior was observed while running the exact same code:
When running as the logged in user, the file is read with no error
When running as the service account, trying to read the file generates the Access Is Denied error with no details
In order to fix this, I had to change the method call from the default (Opening as RW) to opening the file as RO. Once I made that one change, it stopped throwing an error.
I had this issue for longer than I would like to admit.
I simply just needed to run VS as an administrator, rookie mistake on my part...
Hope this helps someone <3
If your problem persist with all those answers, try to change the file attribute to:
File.SetAttributes(yourfile, FileAttributes.Normal);
You do not have permissions to access the file.
Please be sure whether you can access the file in that drive.
string route= #"E:\Sample.text";
FileStream fs = new FileStream(route, FileMode.Create);
You have to provide the file name to create.
Please try this, now you can create.
TLDR : On my end, it had something to do with AVAST ! => Whitelist your application.
All of a sudden, I also got this UnauthorizedAccessException problem in the windows WPF program I'm writing. None of the solutions worked - except I couldn't figure out how to elevate my application to full privileges (not using VS) while at the same time, being already on the administrator account, I didn't feel the need to dig that deep in permission concerns.
The files are image files (jpg, psd, webp, etc.) I wasn't trying to open/write a directory, it has always been a valid path to a file, and I needed to write to the file, FileAccess.ReadWrite was inevitable. The files (and any of their parent directory) were not readonly (I even checked by code prior calling new FileStream(path, mode, access, share) via FileInfo.IsReadOnly) - so what happenned all of a sudden ???
Thinking about : I had an had drive crash, so I unpacked a backup of my solution code from another drive. In the meantime, I added codes in my application to PInvoke APIs to directly read hard drive sectors physical bytes as well as USB plug/unplug monitoring.
I started to get the Exception when I added those, but even though I temporarly removed the related codes from the application, I still got the UnauthorizedAccessException.
Then I remembered one thing I've done long ago, a painstaking similar issue where I wanted my application to communicate sensible data via Wifi, which was to add the executable among AVAST exceptions, and the assembly directory aswell (My app was already among the authorized apps through firewall)
Just did it for my application in AVAST settings, AND THE EXCEPTION IS GONE !!! Two whole days I'm lurking StackOverflow and the web to get moving on, FINALLY !
Details : I can't pinpoint exactly what AVAST didn't like in my application as the only changes I made :
Retrieved then launched the backup code - it worked like a charm, files (images) opens/write without problems (3 days ago)
Added USB detection (3 days ago - Just tested the code, didn't tried to open an image)
Added PInvoke physical drive direct read (2 days ago - FileStream, and the logic to define where/how to scan the damaged drive - Just tested the code, didn't tried to open an image)
Added image format detection starting from Jpg/Jfif.. 2 days ago, got the exception upon testing the code.
While searching for solutions, added an Image Gallery WPF UserControl to diplay pictures based on their signature and check which files gives the exception : almost all of them (some files opens/write okay - why ???)
Tried everything I've found on SO (since the last 2 days) until I opened AVAST settings and whitelist my application.
... now I can move on into adding a bunch of file signatures to retrieve as many datas as I could.
If this may help those who like me, aren't failing on the "I'm passing a directory path instead that of a file", yet, have no time to learn exactly why antiviruses think our own code is a malware.
Just Using the below worked for me on OSX.
var path = "TempForTest";

How to create Application.exe.config in application directory

So I recently updated my application to support a new feature. In the past if the configuration file was deleted by the user it wasn't a big deal. This new feature requires it to exist, and one of the requirements is that, the file exists in the application's installation directory.
I have notice when the file is deleted ( depending on variables I have not figured out ) I get a .NET notification that the configuration file is missing or corrupt. Currently my program then crashes ( I still have to figure out how to duplicate this behavior ) which is the reason for this question.
I am familar with ConfigurationManager. I am having trouble writting the file once the default values are loaded. Forcing a Save for some reason does not seem to recreate the file, at least not in the installation directory, which is a requirement.
I am looking for guidence on how to handle this corner case in an elegant manner. I would post code, honestly its just all failed attempts, which while my attempts do generate a file the contents are not the settings I am looking for.
I am willing to post anything that might be able to help.
Stop using the built-in config support and just use write/read to a file called something.exe.config using the standard XML classes and if that gets deleted, just re-create it from values hard-coded in the executable.
The config file support is supposed to make things easier, if you need to do stuff where it makes things difficult, don't use it.
Something like
var wcfm = new WebConfigurationFileMap();
Configuration newConfig = WebConfigurationManager.OpenMappedWebConfiguration(wcfm, "/");
newConfig.Save();
doesn't work?
You dont. Under normal conditions the program can not write into it's install directory - this is a standard windows security issue and the reason why app application data should reside ni external (from the exe's point) driectories.
If an admin deletes the config file, crash, ask for reinstall. There is nothing you can RELIABLY do, as you can not assume you can write into the folder at runtime. A message followed by an event log entry is the best approach here. Users are not supposed to delete parts of the application.

C# -> Updating an AppSettings.config file on Win7/Vista

I can't see anything on here but I do remember being told that If you want an application to update a config file then it needs to be under ...
**C:\Users\Ibrar Mumtaz\AppData**
Well somewhere there, the reason being is that the user should have permisions to update a config file here and not under the applications install folder. This is the impression that I am under and I'm fairly certain that this is definately the case. As I think I read that on here = p
My question is, is there anybody on here that can shine some light on this as this is the last feature I want to implement before I give my application out to test.
1) First thing is, an installer is needed to set up the folder and then drop my apps config file into it. I already am using the visial studio installer so I have my app packaged up but this point is throwing me off? How do I do this then? I just need someone to show how to do this and I should be O.K reconfiguring my app to look for the new home of the config file.
2) I should be able to work out how to find the folder and locate the config file found within it. As once I know the installer is chucking the config file out into the right folder where the user has permissions then it should be straight forward from there.
Thanks for reading.
UPDATE:
It was pretty straight foward, as the VS Installer has an option to add a special folder so all that was left was to access the folder programmatically and read and write to the config file. ONE PROBLEM? The ConfigurationManager class which I have used to create my config file for my application expects my config file to be local to the application and not miles away in a completey different part of the local FileSystem? Errr help here Plz?
Ibrar
If you are using the VS Settings file to create application setting keys, and have values that the user might want to change in runtime, and save his preferences, just set the scope of those settings to "User" instead of "Application".
That way you will have a setter method for them, and you can edit the Settings.Default instance, and when you are done call the Save() method to persist them to disk.
The file will be saved in the user's "AppData" folder, wherever it is, under some cryptic folder. But you needn't worry about it's location most of the time, since it will be read automatically on the next execute, and persisted to the same location on subsequent runs.
Afaik the installer can be extended with classes that do things.
On INSTALL-action to do could be to
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"My app name");
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
And vice-versa on uninstall.
App.config files are related to where the physical assembly is located I think.
Actually, if your app is running on the user's machine- it will have whatever permissions that user has. So most likely, you can expect to be able to write anywhere on the file system.
However it is possible the user would be running under a restricted acct, and thus not have the permissions. So you could just use the registry to store where your config file is (install folder), then when you try to update it, if it fails for permissions, ask the user to grant it.
Or you could use the Windows standard folders, as you were getting at, because doing so also separates out user data from application data.
Use the Environment.GetFolderPath () method to get the 'special folder' paths in your app.
http://www.programmersheaven.com/2/Les_CSharp_15_p2
http://msdn.microsoft.com/en-us/library/14tx8hby.aspx
If you are talking about application settings found on project Properties -> Settings tab, then there're two different types of settings: user-level and application-level.
If you need to change any settings in run-time, these would be user-level settings (http://msdn.microsoft.com/en-us/library/cftf714c.aspx) and all changes would be buried somewhere in the private folder in your user profile.
If you want to update application-level settings, your best shot would be to do that during software installation. In this case you don't need to look for the configuration file (YourApp.exe.config) anywhere but in the application folder. More likely you would need to create some sort of post-install event handler in your setup package and run some script or another application which would update data in YourApp.exe.config. Everything in the setup package will be executed with elevated priviledges and thus that configuration file would be writeable. BTW, this scenario applies to 2000 and XP, if the user is using limited user account type priviledges.
Because I did not technically find the answer I was looking for, after 6 months I have come back to my application and have managed to produce a solution that does not break my current architecture.
If you are implementing an application to make use of some of the features on offer by the ConfigurationManager then it offers a static method called:
ConfigurationManager.OpenMappedExeConfiguration(); // takes two arguements.
It can be used like this:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = returnUsersAppDataFolderPath();
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
e.g
fileMap.ExeConfigFileName = #"some file path external to your applications install folder."
remember to use '#' symbol in front to allow the compiler to literally treat the string on as is basis.
If the config file can be conveniently locally located then just use the:
ConfigurationManager.OpenExeConfiguration(string exePath)
Above is what you would typically use but for me i needed my config file to located under the users AppData folder so the first option is what I needed. And it does indeed work.
I hope this helps others as it does for me as I want to deploy my application to Win7 and vista environments therefore this question needed asking if I was to stick to using the ConfigurationManager it's a shame the method of choice in the end never really stood out in the first place = ).
If you want to read from your config file then leave a comment and I will show you how I managed to do that also.

Categories