Get OneDrive path in Windows - c#

I have a C# WPF application and I am trying to find a way to get the path to the root OneDrive directory in Windows. How can I do this programmatically? I have searched online, but I couldn't find anything. I wish I could supply some code but I have no clue; I mean, I have checked system environment variables and I couldn't find anything on my machine, thinking that could be a valid solution, but it didn't turn up anything.

With latest update for windows 10, Microsoft introduced new environment variable %OneDrive%, I have checked it on April 2017 update (Creators update) and it is there.

This works for me (Windows 10 Pro, 1803):
var oneDrivePath = Environment.GetEnvironmentVariable("OneDriveConsumer");

On my Windows 8.1 computer, the registry key that holds this information is: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\SkyDrive\UserFolder
I'd try using the Registry.GetValue() method:
const string userRoot = "HKEY_CURRENT_USER";
const string subkey = #"Software\Microsoft\Windows\CurrentVersion\SkyDrive";
const string keyName = userRoot + "\\" + subkey;
string oneDrivePath = (string)Registry.GetValue(keyName,
"UserFolder",
"Return this default if NoSuchName does not exist.");
Console.WriteLine("\r\n OneDrivePath : {0}", oneDrivePath);
I also found the path under:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SyncRootManager\SkyDrive\UserSyncRoots\S-1-5-21-2696997101-1021499815-432504798-1004
HKEY_USERS\S-1-5-21-2696997101-1021499815-432504798-1004\Software\Microsoft\Windows\CurrentVersion\SkyDrive\UserFolder

I get the location of my OneDrive folder using the constant FOLDERID_SkyDrive (https://msdn.microsoft.com/library/dd378457.aspx) and the "GetKnownFolderPath" method from the answer at // Detect the location of AppData\LocalLow.
Although the environment variable "USERPROFILE" combined with "\OneDrive" will sometimes work, if the user has moved their OneDrive folder, the environment variable will actually be a reparse point, and not the actual location.
Tested on Windows 10
Guid FOLDERID_SkyDrive = new Guid("A52BBA46-E9E1-435f-B3D9-28DAA648C0F6");
location = GetKnownFolderPath(FOLDERID_SkyDrive);

For completeness, there seem to be 3 environment variables set:
OneDrive
OneDriveConsumer
OneDriveCommercial
In my case, the first and last are the same (my OneDrive for Business account) and the middle one is my personal OneDrive. I'm seeing the same results on both a domain joined PC and a non-domain joined PC but with both OneDrive configured. On a non-domain joined PC with just my personal OneDrive then the OneDrive environment variable points to the personal OneDrive.
I can't find any Microsoft documentation for this but I think that it may be best to ignore the OneDrive variable and just use the OneDriveConsumer/OneDriveCommercial ones to find OneDrive folders.
Steve

If your are using PowerShell, you can use this :
$ENV:onedrive

private void button1_Click(object sender, EventArgs e)
{
try
{
const string userRoot = "HKEY_CURRENT_USER";
const string subkey = #"Software\Microsoft\OneDrive";
const string keyName = userRoot + "\\" + subkey;
string oneDrivePath = (string)Microsoft.Win32.Registry.GetValue(keyName,
"UserFolder",
"Return this default if NoSuchName does not exist.");
Console.WriteLine("\r\n OneDrivePath : {0}", oneDrivePath);
string Onedrivepath= string.Format(oneDrivePath);
label1 .Text = string.Format(Onedrivepath);
}
catch (Exception)
{
/// throw;
}
}

To keep track of these OneDrive environment variables (It will display all environment variables starting by "one"):
From CMD:
$>set one
OneDrive=C:\Users\my_username\OneDrive - COMPANY
OneDriveCommercial=C:\Users\my_username\OneDrive - COMPANY
OneDriveConsumer=C:\Users\my_username\OneDrive
From PowerShell:
$>dir env: | Where-Object {$_.Name -like "one*"}
OneDrive=C:\Users\my_username\OneDrive - COMPANY
OneDriveCommercial=C:\Users\my_username\OneDrive - COMPANY
OneDriveConsumer=C:\Users\my_username\OneDrive
or
$>Get-ChildItem env: | Where-Object {$_.Name -like "one*"}
OneDrive=C:\Users\my_username\OneDrive - COMPANY
OneDriveCommercial=C:\Users\my_username\OneDrive - COMPANY
OneDriveConsumer=C:\Users\my_username\OneDrive

I was thinking the registry as Smashing1978 mentioned, but I do not have a UserFolder key under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\SkyDrive.
Could you use the %UserProfile%\SkyDrive path?

You must find path under registry ... First run regedit from search box , then under Software - Microsoft - find OneDrive
image description here
Then use that path for you subkey string
const string subkey = #"Software\Microsoft\OneDrive";
Solution source code is here

in VBA use Environ("OneDriveConsumer")

The registry didn't work for me on some PC's.
However, this worked for me:
using System;
using System.IO;
DirectoryInfo di = DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
string path = di.Parent.FullName;

I'm guilty of only skimming this but see some issues with the questions & answers. The question asks "...I am trying to find a way to get the path to the root OneDrive directory...". I'm using Win11 & Win10 (version 10.0.19044 specifically). Both show the same details below with OneDrive settings
There are 2 paths with OneDrive to consider: The local PC path with cached files/folders & the actual OneDrive path that contains everything. Windows lets users keep all or just selected files/directories cached locally. All of the answers focus on the local path. I am giving an alternate set of details because this opens OneDrive in Explorer rather than a web page or the local cache. This also answers the question being asked but uses OneDrive not the local cache.
Get the value of HKCU\Software\Microsoft\OneDrive\Accounts\Personal value: cid (string value). This is the ID needed for a UNC path. The UNC is: \\d.docs.live.net#SSL\[whatever the registry CID is]. This will get you everything in OneDrive, not just what's cached locally on the PC. You can even map a drive to that UNC path & it works.
I have not compared this with OneDrive #work yet, but I will.
Is the poster looking for the local path or for the full OneDrive path?
For the local cache path, it's here: HKCU\Software\Microsoft\OneDrive\Accounts\Personal value: UserFolder (string value)
Relying on an OS variable ties you to specific versions of Win10 or later which might not be a good idea depending on your delivery audience. What I've described covers the local cache + entire OneDrive.
(you don't need a SID or have to convert a SID to a name & you don't need to use OS variables that won't necessarily be present)

Related

How to trigger environment reload using C# .NET?

I am trying to write a custom installer for my application. I am making this installer using C#. One of the features of this is adding my app's directory to PATH.
However, when I do this, I have to reboot my computer to be able to access the updated PATH variable. When using a setup scripting tool like Inno setup, I can set it to somehow reload the environment to access the updated PATH immediately without having to reboot. How can I replicate this behaviour using C#?
I am sorry if this is a duplicate question but I am unable to find anything on this.
It turns out that I was trying to modify the registry. You can access it immediately by using System.Environment
var name = "PATH";
var scope = EnvironmentVariableTarget.User; // or User
var oldValue = Environment.GetEnvironmentVariable(name, scope);
var newValue = oldValue + #";C:\Path\To\Add";
Changing the PATH variable in Windows should not require a reboot. A simple solution is to add the directory containing your executable and any folder it uses to your PATH variable. For example:
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86).ToString() + ""
ather for Program Files (x86) on " + System.Environment.OSVersion.Name

Get BaseDirectory of an application from a Windows Service

I have a winform application ABC. I'm installing this on my client devices using clickonce. In it's BaseDirectory (which is AppData\Local\Apps\xx\yy\zz\ for my application). In the zz folder I have a zip folder which I need to access from a windows service. Is there any way I can get the AppData location from my win service? Is it even possible? I had the assumption it's not possible since it means a third party can affect the application.
The best option seems to be what Alex K suggested in the comments, save it in the registry upon installation and retrieve it with your service.
Another option might be using MSI and there's a C# wrapper for it on GitHub.
An example:
// Look for installed products containing 'Word' in their name and show their installed location
foreach (var p in InstalledProduct.Enumerate())
{
try
{
if (p.InstalledProductName.Contains("Word"))
Console.Out.WriteLine("{0} is intalled in {1}", p.GUID, p.InstallLocation);
}
catch (MSIException ex)
{
// Some products might throw an exception trying to access InstalledProductName propoerty.
}
}
It is partially possible. You can acquire the appdata local directory on the client system from your service code using:
var p = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
Then you can add the part that is specific to your application ("xx/yy/zz") as that would not be anywhere in the environment. I would suggest using:
Path.Combine(p, "xx/yy/zz/yourfile.zip");
If the special folder above is not the one you need you can refer to the rest of the enumerated values here on msdn for the SpecialFolder Enumeration

Creating a folder on the desktop

I want to create a folder on my current user's desktop folder, however; I keep getting an access denied message. I have full write permissions under my profile in IIS.
string activeDir = #"C:\Users\dmm\Desktop\";
string newPath = System.IO.Path.Combine(activeDir, "mySubDir");
System.IO.Directory.CreateDirectory(newPath);
Any help would be appreciated.
Try using the built in objects to get the desktop path, and let .NET also handle the path building for the new folder. You will also want to check if the directory exists first.
string newFolder = "abcd1234";
string path = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
newFolder
);
if(!System.IO.Directory.Exists(path)) {
try {
System.IO.Directory.CreateDirectory(path);
} catch (IOException ie) {
Console.WriteLine("IO Error: " + ie.Message);
} catch (Exception e) {
Console.WriteLine("General Error: " + e.Message);
}
}
When you deploy an application on IIS by default it is executed with ApplicationPoolIdentity. Which is virtual user created and named as IIS AppPool\YourPoolName If this virtual user does not have write access to your desktop. You get that exception.
You have two options.
Give ApplicationPoolIdentity user write access to Desktop directory.
goto Desktop folder and add user IIS AppPool\YourPoolName with write access :
Change pool Identity to user which has write access to directory.
Go
IIS->Application Pools -> Your AppPool ->Advanced Settings -> Identity
->
Select Custom Account and click set button. and there you enter your windows user credentials.
I would recommend first option.
There are many to consider here, first of them being that your application is an ASP.NET application, and every current user will be different. If your application — just assume — runs correctly on your machine, it will never run on hosting environment because they do not grant write permissions to special folders and user accounts.
That said, you need to work in physical paths in order to create your directories.
var path = "C:\\Users\\afzaa\\Desktop\\";
var folder = Path.Combine(path, "folder");
Directory.CreateDirectory(folder);
The result of the above code is,
As you can see, the code properly works and has no issue at all in execution.
There are few things to note:
Your application has read/write permissions. Check IIS for that.
Your code can actually lookup the path you are trying to access. That applies to any folder inside Desktop too, a sub folder may have special permissions applied.
Do not do this, write the content online in your hosting domain. Users have different accounts and structures for folders and thus this will not work — Desktop path is different.
If you want to users to download the file, simply stream the file down and let them save it where they want to.
https://forums.asp.net/t/1807775.aspx?Create+e+New+Folder+Access+Denied+
https://answers.microsoft.com/en-us/windows/forum/windows_xp-files/unable-to-create-the-folder-new-folder-access-is/ac318218-a7b2-4ee2-b301-2ad91856050b
.NET MVC Access denied when trying to create Directory
If you ran your logic from an IIS application, you should use Server.MapPath:
System.IO.Directory.CreateDirectory(Server.MapPath(newPath));

ERROR: System.Environment.SpecialFolder' does not contain a definition for 'CommonApplicationData'

I have the code to save a file in a folder in directory
string timestamp = DateTime.Now.ToString("MM-dd-yyyy.HH-mm-ss");
var file = File.Create("Owe-Data.txt" + timestamp);
var com = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase + timestamp + #"\Data" + file;
MessageBox.Show(com);
if (!Directory.Exists(com))
{
Directory.CreateDirectory(com);
}
using (var sw = new StreamWriter(com))
{
sw.WriteLine(InputData);
}
}
i Displayed COM it gives path bt i cant see the Data folder or Owe-Data file at that path
Anybody can tell why this happening, or should i save the Data folder in current directory where this prgram running? bt i dnt know how to reach that path. Any solutions ??
Working on windows phone 5, visual studio 2008 .NET framwork 2.0
As per the Exceptions section of documentation,the above exception is thrown when
ArgumentException ------- folder is not a member of System.Environment.SpecialFolder.
It means the OS where you are running this command does not have Environment.SpecialFolder.CommonApplicationData as one of the special folder.
For knowledge,
Environment.SpecialFolder.ApplicationData is the most common one. This folder holds per-user, non-temporary application-specific data, other than user documents. A common example would be a settings or configuration file.
Environment.SpecialFolder.CommonApplicationData is similar, but shared across users. You could use this to store document templates, for instance.
Environment.SpecialFolder.LocalApplicationData is a non-roaming alternative for ApplicationData. As such, you'd never store important data there. However, because it's non-roaming it is a good location for temporary files, caches, etcetera. It's typically on a local disk.
I think the problem may be that Environment.SpecialFolder.CommonApplicationData is common and shared between different users and the user with which you have logged in is not having rights to access the folder or the Visual Studio has not been started in Admin mode.
EDIT Look at link and try to add a manual registry Common AppData defined in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\
Given you are asking about a .NET Windows Phone application as per the tags
I think your problem is that a .NET Windows Phone application does not have direct access to the file system; it can only access IsolatedStorage this is by design.
I would quote a Microsoft source for this but I can't seem to find one!
EDIT
See this article from MSDN

Access denied to path , when uploading image to folder in server

Am getting error when you are going to upload the file on specified folder in the server. Here I am going to upload P6100083.jpg in storeimg folder. When I am going to upload I am getting the following error:
Access to the path 'C:\inetpub\vhosts\bookmygroups.com\httpdocs\storeimg\P6100083.jpg' is denied.
Can anyone help me... How to use permisiion and were to use...
My code is while uploading image
if (FileUpload1.HasFile)
{
float fileSize = FileUpload1.PostedFile.ContentLength;
float floatConverttoKB = fileSize / 1024;
float floatConverttoMB = floatConverttoKB / 1024;
string DirName = "storeimg";
string savepath = Server.MapPath(DirName + "/");
DirectoryInfo dir = new DirectoryInfo(savepath);
// string savepath = "C:\\Documents and Settings\\ssis3\\My Documents\\Visual Studio 2005\\WebSites\\finalbookgroups\\" + DirName + "\\";
if (fileSize < 4194304)
{
string filename = Server.HtmlEncode(FileUpload1.FileName);
string extension = System.IO.Path.GetExtension(filename).ToUpper();
if (extension.Equals(".jpg") || extension.Equals(".JPG") || extension.Equals(".JPEG") || extension.Equals(".GIF"))
{
savepath += filename;
FileUpload1.SaveAs(savepath);
}
}
}
Thanks in advance
I have no success making my upload or any write operation on filesystem work on IIS7.
Still getting the error: Access to the path is denied.
My AppPool is running under Network Service. I have granted all kinds of accounts Full Control (Network Service, Network, IIS_IUSR, Administrator, Users, Everyone), restarted the webservice several times, studied all IIS7 settings, googled for two hours and nothing works.
IIS7 and WS2008 s-u-c-k-s. Sorry for the term. Anybody can help?
I just wanted to add: I noticed that in the upload's destination folder's Properties there's this checkbox named "Read-only (Only applies to files in folder)" and it's checked. It cannot be unchecked, comes back checked after unchecking and clicking the OK button. Is that IIS7 guarding it?
Editing this message to add the SOLUTION: My admin has turned off the silly UAC "the security confirmation feature" on our server, restarted the machine and it works now. No "write" access rights for "Network Service" or any other IIS-used account was needed. When accessing the file system in a ASP.NET web application using the integrated authentication and having the impersonation set to true in its web.confing, the file system seems to be accessed by the authentified end-user's account, not by the Network Service account which the AppPool is running under. (Many people tell you to set Network Service permissions, but that is not true.) So you need to set the "write" permissions for your end-users (usually domain users: "DOMAIN\domain users") on your particular folder.
Oh yea, and the "Read-only (Only applies to files in folder)" checkbox mentioned above does not seem to have any effect. However Microsoft says "some programs might have problems writing to such folder and you should use command line statement "attrib -r -s" to get rid of the Read-Only attribute" -- but it won't work. It will stay there checked-grayed. But don't worry about that. Microsoft becomes more and more silly every day.
Indead, it's a server issue.
You need to verify if the user underlying your application pool has write access to the directory.
If you use IIS7, you have a new feature that helps you give custom write to this user and dun need to change the user.
Look at this link:
http://www.adopenstatic.com/cs/blogs/ken/archive/2008/01/29/15759.aspx
Hope this helps.
This is a server issue. Make sure you have the necessary rights to write files.
Btw, since you call ToUpper() on extension there's no reason to test for ".jpg".
If you are using Plesk Panel, go to file manager of Plesk Panel. List files and folders inside "httpdocs". Each file and folder has a lock icon at the very right. Click that of "storeimg" folder to change permissions. Click advenced button. Give full permission to these:
Plesk IIS WP User (IWPD_214(your_login_name))
Plesk IIS WP User (IWPD_214(your_login_name))
And click OK.
First you check the permission is enable or not if not then go to that folder which folder has to be use for containing files then right click on folder then there will be display folder properties then click on security there will be display multiple number of user which user have to be permit then click allow that all permission will be activated.
First, make sure your code runs fine locally (I assume that something you've already done).
Then deploy to your TEST or UAT environment. If you're having issue there, then this is a configuration issue. Make sure the service account under which your website's app pool is running has access to the folder.
Please make use of C# method Path.Combine() to build up your path and avoid issues with leading or trailing / and \.

Categories