(How) can I select a Windows Store app with a file browser? - c++

I'm working on an introspection utility which eventually asks the user to specify the executable to use for launching the application. Now I'd like to add support for so-called "Windows Store apps" (formerly known as "Metro" apps, I believe). However, it's not clear to me how they are stored locally.
I read about how Windows Store apps are packaged and deployed, and apparently it's common to distribute them as .appx files, generated by tools like makeappx. However, I don't see if/where they are stored locally.
Does it make sense to address them like ordinary executables at all, i.e. via a file name? Or is there rather a more appropriate method? I noticed that in the registry, some (all?) of the Windows Store apps I have installed are listed beneath
HKCU\Software\Classes\ActivatableClasses\Package
Is there some API available for handling this registry tree, to do stuff like "Get me the user-visible name" or "Get me the AppUserModelId so that I can launch the app"?

Related

How to add layer on top of file system? Like cache in OneDrive or Google Drive

I'm looking for a way (using C# .Net or C++ and WinApi or anything) to add a layer between filesystem and client application to add custom behaviour.
Like OneDrive and Google drive application on Windows. You can browse files normally but if given file is missing from a drive it will be downloaded. I need to do something similar. And I need this solution to be transparent to other software (explorer and any other software that accesses files on drive).
I really even know what to call it. So if you have a name for that type of functionality please let me know.
Here are some approaches to building a virtual file system on Windows:
Using Cloud Files API. OneDrive is built using this API. It is designed for slow-speed remote (cloud) storage, such as Document Management System. Here are some features that it provides:
On-demand loading. You can load the file content into the local drive only when an application is accessing it the first time. The folder listing can be done during the first access to the folder.
Offline files support. You can pin/unpin files to keep on the local drive when the server is unavailable.
Download/upload progress reporting.
Integration with Windows File Manager. Each item shows offline status, pinned/unpinned status, in-sync status, and download progress.
Messages and error notifications to the user, as well as file system status reporting.
The driver that this API is using is installed with Windows by default and does not require installation. Here are some tools to build an OneDrive-like application:
CloudMirror sample in C++ from Microsoft. Code on GitHub.
User File System from IT Hit provides example in .NET. Code on GitHub.
Using Projected File System (ProjFS). It allows you to represent (project) some hierarchical technical data as a file system. It is designed for high-speed back-end storage, such as for example registry. Here is its major feature:
Hides the fact that the data is remote. The user "thinks" that the files are in the local file system and does not have any status information. The user does not know if the file content is available/unavailable or online/offline.
ProjFS is not installed by default and requires Windows component installation (thank you IInspectable for this info). Here are some tools to build with it:
Programming guide. Sample: Virtual File System for Git.
Using Shell Namespace Extensions. Typically used to create a UI extension for Windows File Manager. For example, Windows Recycle Bin and Printers are namespace extensions. They are not available via standard Windows File API and applications can not read/write to it unless it redirects to a real file system behind it. Here some features that it provides:
You can customize the Windows File Manager toolbar, shortcut menus, folder view, tree view, and status bar.
You can extend the Windows File Manager hierarchy, adding new custom nodes that look and behave like files and folders (cut/copy/paste, drag-and-drop, etc), without building a functional file system behind it.
Shell Namespace Extensions are part of Windows and does not require additional components installation. In many cases, you will use Shell Extension to add shortcut menus and items on a toolbar in Windows File Manager while building the actual file system using Cloud Files API or ProjFS. Links to start working with Shell Namespace Extensions:
Understanding Shell Namespace Extensions
Extending Shortcut Menus
What you are looking for is commonly called a "Virtual File System". To applications it looks like a file system, but the implementation is at your discretion, allowing you to materialize objects in any way you see fit.
On Windows you have several options to implement a virtual file system. The most common and widely supported infrastructure is the Shell Namespace. It allows you to register extensions, that appear as items (e.g. files or folders) in the file system. It's not entirely trivial to write a Shell Namespace Extensions, but it's not rocket science either.
A more recent addition to Windows is the Projected File System, that provides everything you need to build a virtual file system in user code. It ships as an optional component in Windows, and needs to be explicitly installed first. For an implementation that uses the ProjFS, see the VFS for Git github repository.

Windows 8: Application is not able write to C:\ProgramData\

I'm porting my application on Windows 8. Program uses path
C:\ProgramData\MyProgramName\
for storing backups.
It works good on Windows 7, but it got "Access Denied" when I run it on Windows 8.
What is the proper way and place to store my program's backups (not related to any particular user) ?
I see many programs storing their non-user related application data in the common application folder. Ok, actually what they do is create a folder inside the common application folder to store their data.
To get the path to the common application folder, you can call the SHGetFolderPath function with CSIDL_COMMON_APPDATA as the folder id. If don't have to support anything earlier than Windows Vista then you can call the SHGetKnownFolderPath function instead, and pass FOLDERID_ProgramData as the known folder id.
Ah! I did not know that the common application folder is not-writeable by normal users. Luckily there appears to be a recommended solution. See this article on MSDN, Data and Settings Management which states the following "If an application requires normal Users to have write access to an application specific subdirectory of CSIDL_COMMON_APPDATA, then the application must explicitly modify the security on that sub-directory during application setup. The modified security must be documented in the Vendor Questionnaire."
C:\ProgramData has security settings that prevent standard user from writing there. This is not new in Windows 8, Windows 7 was the same, and the equivalent folder on Vista is also secured in this way. Perhaps your Windows 7 environment has UAC disabled, or perhaps you have secured C:\ProgramData or C:\ProgramData\MyProgramName to permit write access to standard user.
There are a couple of approaches to the use of this folder. Some applications write there only during installation whilst the installer process is running elevated. Then the application itself, which runs as standard user, can read, but never attempts to write.
Another approach is for the installer to create a sub folder of C:\ProgramData that is secured to allow write access for standard user, or whatever user/group that you the developer deem appropriate.

How can I retrieve the Windows profiles directory path remotely?

I'm trying to retrieve the path of the profiles directory across various versions of Windows. In older versions that might be [drive]:\Documents and Settings, on newer ones it's [drive]:\Users. There are several ways to do this locally without a problem, however I need to find the path on a remote machine that I've connected to.
Remote Registry is enabled.
I have an impersonation token and can successfully gather information from the remote host via the Net API, etc.
I have access to the administrative share, and therefore all the files on the remote drive.
Here's a list of other important caveats.
It's a C++ project.
It doesn't seem to be possible for GetProfilesDirectory or GetUserProfileDirectory to operate in a remote context. If I'm wrong about this please let me know but in all my experiments the function has returned something from the local machine.
I can't use WMI, we tried many times to integrate WMI functionality into our project and it just didn't work.
I would prefer to do as little "screen scraping" as possible. If you have an idea that doesn't involve reading from some text file and parsing the result, I'd love to hear it. But I'd appreciate any useful answer really.
The profile directory information in the registry don't seem to be useful because it contains environment variables, and like GetProfilesDirectory, the environment variable expansion function does not seem designed for work with remote hosts. This means that the solution wouldn't work if I was making the call from a newer Windows machine to an older Windows machine or vice versa.
The solution should be general enough to work between hosts that might be running any version of Windows from Windows Server 2003 to Windows 7.
Thanks in advance for whatever ideas you might have. Ideally I'd just like to be able to force GetProfilesDirectory to operate on the remote host so if you know how to do that I'll love you forever.
If you have access to the remote registry, you should be able to look at the key where the profile directory and the profile list is kept:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

Creating installer for a c++ windows service Dynamically

I have created a windows service which checks for the status of the printer.
The user can download this service from a website. I need to query for the status of printers used by this user. So when the user clicks on the download button I want to store the user information in a file which my service can use. The service will use this information to fetch the printers from the database. I want to include this file in my installer. So I have to create the installer at runtime(i.e. when the user click the download button on my website).
How can I create the installer for the win service dynamically using C#?
NOTE: my win service is written in C++. I know about WIX.
quite a few years ago, when I did some work with InstallShield, it was possible to specify in the installer project which file(s) you don't want to be compressed and packed into the .cab files (or whatever they are called nowadays) when generating the installation package. Such a file would be left as-is and separate in the package, and you could later replace it with another file with the same name (I think I actually did something of the sort). So you can have a dummy file when building the install package, and then replace it on the fly with the right one.
I am not familiar with modern tools, but am quite sure this functionality is preserved as it is quite useful.
In WiX you can create custom actions which are arbitrary code you write (You provide the .dll which can be built using C++). In the custom action you can generate your user/location customization file.

Windows Limited User Installation

I have a Win32 application that includes an EXE, an ActiveX control (DLL) and a COM server (EXE) and I am using Inno Setup 5 to build my installer. Many of our customers use limited user accounts where the user has no admin rights and because the COM components require to be registered (which writes to HKEY_CLASSES_ROOT), my setup file must run with elevated (admin) privileges. I think this in unavoidable (sadly, I can't use registration-free COM because of the EXE COM server I have). However, I would like to create an update installer that can be ran as a limited user and am looking for some advice.
What I am thinking is the following:
The initial setup (first time installation) installs the application into %ALLUSERSPROFILE%\Application Data\CompanyName\AppName instead of %PROGRAMFILES%. The COM components are registered as normal (as they won't already exist).
Subsequent updates (using a different Inno Setup script) will simply copy the new files into %ALLUSERSPROFILE%\Application Data\CompanyName\AppName. Hopefully even a limited user will have write access to this folder and as the COM components have already been registered, admin access won't be required.
This would mean that my customers could upgrade to the latest and greatest version without the hassle of using an Administrator account. Is this acceptable or is this likely to bite me on the backside? I'm pretty sure Google Chrome does something similar but as it has no COM components (as far as I can tell) even the initial setup can be as a limited user.
Any advice from others who have faced this issue would be very welcome indeed.
OK, I found a way to create a limited-user installation script with both my COM server and COM objects being registered per-user.
I am using the latest version of ATL (v9) that ships with MSVC 2008 to create my COM server and COM objects. Turns out that you can register the COM server per-user via the new /RegServerPerUser switch. I tested this with limited user accounts on XP, Vista and Windows 7 and it works perfectly.
Next, the COM controls. Again, ATL9 to the rescue. You can register a control per-user by ensuring that RegSvr32 calls your control's DllInstall function, passing it a command-line parameter of user. So, to register a control in this way you simply do:
regsvr32.exe /i:user /n MyControl.DLL
Again, I tested this on XP, Vista and Windows 7 and it works fine.
I then made the following changes to my Inno Setup script:
The default installation folder will be {pf} (i.e. C:\Program Files) if the user has Admin rights. If not, then it defaults to {commonappdata} (i.e. C:\Documents and Settings\All Users).
Register my COM server using the new /RegServerPerUser switch.
I removed the regserver flags from my COM objects and instead added support to call regsvr32 using the new 'user' switch.
All of these changes are easy to do using the Inno Setup {code} feature.
Thanks to Kim for setting me down the per-user COM install path.
I don't know for sure, but I seem to recall COM servers support per-user installation, and maybe that goes for EXE servers as well.
If so, change your registration code to write information to HKEY_CURRENT_USER\Software\Classes instead of HKEY_CLASSES_ROOT.
The COM infrastructure should do the lookup first per-user and then per-machine.
It's worth an experiment anyway.
If you dumped inno-setup and used MSIs - MSI files support the idea of limited user installation of patches. An administrator must authorize the initial install, thereafter, digital signatures in patch msi files are processed by the elevated msi service without requiring user elevation.
You can duplicate this basic idea yourself - during an initial administrative install, install a service component that has the necessary access. When processing patches, ask the service process to process the EXE COM server registrations.
You need to rethink your approache ... write access to a folder than can also allow for program execution by the same user is the cause for 99% of all virus/malware functionality. Please learn a little about Software Restriction Policy and the new App Locker behavior built into Windows 7 so that the computing infrastructure can move forward not backward.