Cannot create StorageItem in Outlook Add-In - c#

I'm trying to run this code:
this.storage =
Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts)
.GetStorage("ws_up_storage", Outlook.OlStorageIdentifierType.olIdentifyByMessageClass);
It runs perfectly well on some machines, but on others it throws this exception:
I also tried other folder names, like olFolderInbox, olFolderCalendar. I've looked at Microsoft docs for this, and it says this error is to be expected if the folder is one of the following:
The folder is a Microsoft Exchange public folder, an Internet Message Access Protocol (IMAP), MSN Hotmail, or a Microsoft SharePoint Foundation folder.
The user permission for the folder is read-only.
The store provider does not support hidden items.
The sad fact is, I do not know how to check which one of these is true and if it's at all possible.
How would I go about determining the cause of the problem and addressing it?

The easiest way to handle all these cases is to try to get a storage. You will need much efforts to implement all cases. The PR_MDB_PROVIDER property allows to identify the store provider, but not all cases such as user permissions for the folder and etc. You can use the try/catch block where you may check the error code - 0x80040102 (MAPI_E_NO_SUPPORT).
However, you may use any low-level property viewers (for example, a free open source tool - MFCMAPI) for exploring Extended MAPI property values. Thus, you may find all the required info about not supported scenarious.

The error 0x80040102 is MAPI_E_NO_SUPPORT, which means the store does not support hidden (associated) items.
Read the PR_MDB_PROVIDER property (DASL name http://schemas.microsoft.com/mapi/proptag/0x34140102) using PropertyAccessor.GetProperty. The returned 16 byte array will be specific for each store kind. E.g. for an Exchange store, it will be pbExchangeProviderPrimaryUserGuid (5494A1C0297F101BA58708002B2A2517). Take a look at any object in the store in question using OutlookSpy (I am its author - click IMessage, IMAPIFolder, or IMsgStore) to see the PR_MDB_PROVIDER property.

Related

Get file / directory Owner as displayed in Windows Explorer

When I look at a file or folder in Windows explorer, it generally shows the Owner as a specific user; in my environment, showing as <domain>\<username>. It shows this information both when I add the Owner column to a folder view, and by right-clicking on a file and looking at the Details tab. I think this is what most people expect to see when they think about the Owner of a file or directory.
I want to grab this owning-user information for a large number of files and folders. However, when I do what every tutorial, blog post and forum answer suggests to get the Owner programmatically in powershell, it shows the Owner as BUILTIN\Administrators:
PS:>Get-Item '.\file.txt' | Get-Acl | Format-List
Path : Microsoft.PowerShell.Core\FileSystem::Z:\path\to\file.txt
Owner : BUILTIN\Administrators
Group : <domain>\Domain Users
Access : NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
<domain>\<myusername> Allow FullControl
Audit :
Sddl : <lots of fancy letters>
There are various posts around which explain why this happens (TL;DR: items created by users who are members of the Administrators group), so don't need to retread that here. And I can see that the info I'm really looking for is there as one of the System.Security.AccessControl.FileSystemAccessRule objects under the Access property. I am considering workarounds including filtering BUILTIN / NT AUTHORITY records out of the Access list, or perhaps filtering on a class as in this helpful question.
However, those solutions seem both inefficient and inelegant. In the UI, Windows seems to "know what I mean" when I want to see the Owner of an item. So it seems really strange that there's no more straightforward way to grab that information in code.
Where does Explorer pull its Owner information from? Is it really doing some kind of inefficient, heuristic list-filtering under the hood as well?
Or must there not be direct way to approach this?
Solutions in powershell, c# or any .net language gratefully received!
Tried and failed:
The solution in this question of calling .GetAccessControl().GetOwner(typeof(System.Security.Principal.SecurityIdentifier)) first, and then .Translate(typeof(System.Security.Principal.NTAccount)) on the result, has not worked for me; still outputs only BUILTIN\Administrators.
cmd.exe's dir <file> /Q gives the same, as suggested in various places including this answer.
Have also found that $file.GetAccessControl() yields the same, unhelpful info as the Get-Acl commandlet.

Manage file custom properties (Get&Set) programmatically - C#

I'm implementing a C# Windows console application to manage files in Windows Explorer. At this point of my work I need to create file custom properties and both set and get their values. I've read many web articles, and I understand that I can't do this for each file, it depends on the type/nature of the selected file... and this is ok for me, this is a limit that I took into account and accepted before starting my work.
Please consider that I want to manage these properties without using the file related application (for example, in case of a .docx file I don't want to open the Word application and then work with Microsoft.Office.Interop.Word.Application and Microsoft.Office.Interop.Word.Document classes). Cases do in fact exist where it is possible to right-click on a file in Win Explorer, select 'Properties' and then find a tab named as 'Custom' where you can search, read and set custom properties.
What I want to do is manage (Read & Write) this file Custom information programmatically.
Any hint? Thanks!
EDIT #1:
I tried to follow the Simon Mourier's hint but unfortunately it does not work, I was not able to SET the property value. I tried also the Rod Howarth's hint but it fails when you try to set the value of an existing custom property... moreover, using the DSOFile library there are problems related to the persistence of the saved custom property.
See this. It is about office file custom properties, but there is one answer describing the method how to get custom properties of any file (as far as I anderstood, even txt file can have some)
This solution seems working fine if you need to set the value of an existing custom property; if you need to create a new born custom property, then you must use the Add(string sPropName, ref object Value) method of the CustomProperties collection.

WinRT: App to enumerate files outside libraries and known folders

I am working on a Metro app that shows the content of a given folder in a ListView control.
MS decided that developers don't need the System.IO.Directory class and removed it entirely from the framework.
I am looking for a replacement to enumerate files in C# in a metro style app. I have checked all the enumeration samples provided by MS and they all seem to only enumerate the Windows Libraries using the KnownFolders class, something like:
StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
and calling the GetFilesAsync() or GetFoldersAsync() methods depending on your needs. These are all gold if I wanted to enumerate only inside the pictures or music library. However I am looking to enumerate files on directories that are not included in a library.
Anyone knows how this is possible in WinRT???
You are, by design, extremely limited in this area for Metro apps. The idea is that a Metro app is only given access to those things that it is trusted to access, so you can either:
access local storage, specific to your application
access a handful of well-known storage locations, or
access a specifically granted location.
Take a look at http://msdn.microsoft.com/en-us/library/windows/apps/hh464959.aspx to get an idea as to what you'll be able to access.
From http://tirania.org/blog/archive/2011/Sep-15.html :
When you use C# and VB, you are using the full .NET framework. But
they have chosen to expose a smaller subset of the API to developers
to push the new vision for Windows 8.
And this new vision includes safety/sandboxed systems and asynchronous
programming. This is why you do not get direct file system access or
socket access and why synchronous APIs that you were used to consuming
are not exposed.
Now, you notice that I said "exposed" and not "gone".
What they did was that they only exposed to the compiler a set of APIs
when you target the Metro profile. So your application will not
accidentally call File.Create for example. At runtime though, the CLR
will load the full class library, the very one that contains
File.Create, so internally, the CLR could call something like
File.Create, it is just you that will have no access to it.
This split is similar to what has been done in the past with
Silverlight, where not every API was exposed, and where mscorlib was
given rights that your application did not have to ensure the system
safety.
You might be thinking that you can use some trick (referencing the GAC
library instead of the compiler reference or using reflection to get
to private APIs, or P/Invoking into Win32). But all of those uses will
be caught by AppStore review application and you wont be able to
publish your app through Microsoft's store.
You can still do whatever ugly hack you please on your system. It just
wont be possible to publish that through the AppStore.
So there's probably no official way, and if there's an unofficial way, it probably won't be accepted to the app store.
Just in general this makes sense: I don't want to download a seemingly legit application just to have it scan my hard drive and find my "budget.xls" spreadsheet which includes my banking/credit information.
EDIT: it is possible to grant temporary access to secure files/folders through WinRT's file picker, but it has to be invoked and chosen explicitly by the user.
You can use the StorageFolder.GetFolderFromPathAsync Method to get a StorageFolder instance from a path.
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(#"C:\...");
Note that you may not have permission to do this for all paths on your machine though.
Similar situation. Wanted to access chrome bookmarks file to parse. Had to use FileOpenPicker initially, but the file that it returns can be "cached" in the futureaccesslist(?) for subsequent retrieval.

What is an effective way to test if a user has permissions to some files?

Visual Studio c# Xml File Permissions
I need to find a way to determine if a user have permissons to access a document from either a url or a local directory. How would I go about checking their permissions IE what method would I use? If it helps or makes a difference what so ever I am pulling the addresses out of an XML file as a string and running each individual node pertaining to location.
Edit: The goal is to Filter the Xml file to display if the user has access to the file.
The simplest and most effective way is to simply try to access the file. If the user doesn't have permission you'll get an exception (UnauthorizedAccessException).
Trap that (and any other specific exception that could be raised) and display a suitable error message.
I have used FileInfo in the past and it was quite useful.
see MSDN link on exceptions it throws

WPF/C#: Where should I be saving user preferences files?

What is the recommended location to save user preference files? Is there a recommended method for dealing with user preferences?
Currently I use the path returned from typeof(MyLibrary).Assembly.Location as a default location to store files generated or required by the application.
EDIT:
I found two related/interesting questions:
Best place to save user information for Windows XP and Vista applications
What's the way to implement Save / Load functionality?
EDIT #2:
This is just a note for people like me who had never used settings before.
Settings are pretty useful, but I had to do a whole bunch of digging to figure out what was going on (coming from the Python world, not something I am used too). Things got complicated as I wanted to save dictionaries and apparently they can't be serialized. Settings also seem to get stored in 3 different files depending on what you do. There is an app.config, user.config and a settings.setting file. So here are two more links that I found useful:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/ddeaca86-a093-4997-82c9-01bc0c630138
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/efe370dc-f933-4e55-adf7-3cd8063949b0/
You can use the Application Settings easily enough.
If you haven't done so before just right click on the project and choose Properties. Select the Settings tab. Make sure you chose "User" for the scope (otherwise the setting is read-only).
The code to access this is simple:
forms.Width = Application1.Properties.Settings.Default.Width;
If you need to save it:
Application1.Properties.Settings.Default.Width = forms.Width;
Application1.Properties.Settings.Default.Save();
In the sample above, Width is the custom setting name you define in the Settings tab and Application1 is the Namespace of your application.
Edit: Responding to further questions
You mentioned you wanted to store Dictionary objects in the Settings. As you discovered, you can't do this directly because Dictionary objects are not serializable. However, you can create your own serializable dictionary pretty easily. Paul Welzer had an excellent example on his blog.
You have a couple of links which sort of muddy the situation a little. Your original question is where to save "User Preference Files". I'm pretty certain Microsoft's intention with the Settings functionality is exactly that... storing user skin preferences, layout choices, etc. It not meant as a generic repository for an application's data although it could be easily abused that way.
The data is stored in separate places for a good reason. Some of the settings are Application settings and are read-only. These are settings which the app needs to function but is not specific to a user (for example, URIs to app resources or maybe a tax rate). These are stored in the app.config.
User settings are stored in an obfuscated directory deep within the User Document/Settings folder. The defaults are stored in app.config (I think, can't recall for certain off the top of my head) but any user changes are stored in their personal folder. This is meant for data that changes from user to user. (By "user" I mean Windows user, not your app's user.)
Hope this clarified this somewhat for you. The system is actually pretty simple. It might seem a little foreign at first but after a few days of using it you'll never have to think of it again... it just works.
When running as non-admin or on Vista you can't write to the "Program files" folder (or any sub folder of it).
The correct location to store user preference is (replace MyCompanyName and MyApplicationName with the correct names, obviously)
On disk:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\MyCompanyName\\MyApplicationName"
Or in the registry under the key:
HKEY_CURRENT_USER\Software\MyCompanyName\MyApplicationName
Those location are per-user and they work with non-admin user, several users using the same computer, fast user switching, terminal services and all the other ways people can interact with your software.
If you need a common location for all users then:
It will only work when the user run as an administrator
It will not work reliably on Vista
You have to take care of everything yourself (like two users running the application on the same computer at the same time via fast user switching).
and the locations are:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationCommonData) + "\\MyCompanyName\\MyApplicationName"
Or in the registry under the key:
HKEY_LOCAL_MACHINE\Software\MyCompanyName\MyApplicationName
You can use isolated storage. You can isolate by user, assembly and/or domain.
Introduction to Isolated Storage
http://msdn.microsoft.com/en-us/library/3ak841sy(VS.80).aspx
Types of Isolation
http://msdn.microsoft.com/en-us/library/eh5d60e1(VS.80).aspx
the following seems to be the best option:
Application.UserAppDataPath

Categories