How to create a property store binary file - c++

I'm trying to implement an icon-based property in Windows File Explorer, and my understanding from this post is that it requires returning a property store binary file from the property handler. Does anyone know how to create a property store binary file? After searching, I've come across some documentation on the specification, but I don't see any examples of how to create one. Thank you very much.

You don't need any binary file, you just need an implementation of IPropertyStore. You can create one using the PSCreateMemoryPropertyStore method.
IPropertyStore *ps;
if (SUCCEEDED(PSCreateMemoryPropertyStore(IID_PPV_ARGS(&ps))))
{
// do your work
ps->Release();
}

Related

How can I get the logging directory of a RollingFileAppender from log4cxx?

I'm using XML to configure log4cxx. The appender is a RollingFileAppender that outputs to a folder like yyyy/MM/dd/HHmm, and I need to know what that folder is at the end of the program.
I can't get the current yyyy/MM/dd/HHmm at runtime because that value will likely be different than it was when the log directory was created. After scanning log4cxx's documentation, I found only one function that was relevant:
log4cxx::FileAppender::getFile()
which returns the file that an appender is logging to.
The problem with that is that calls to log4cxx::Logger::getAppender() yield only AppenderPtrs- I could dynamic_cast this into a FileAppender if I know that's the ultimate type, but this introduces uncertainty into the program. Is there really no way to get the current log directory from log4cxx?
Thanks!
There is currently no(easy) way to get the name of the file that the RollingFileAppender is using.
Using Logger::getAppender() is the best way to get the correct appender that you are looking for. Since the appenders should all have unique names, there shouldn't be any issue with casting to the correct type. If you want to be safe about casting, use log4cxx::cast<FileAppender>( AppenderPtr ) which will return an invalid pointer if the object is unable to be casted to the correct type.

Read 'Extended' file properties (C++)

Is there a way to get all the properties and values of any file under the details tab using only c++ Code?
All extended file properties: link
I have seen solutions for c# but not c++. link
I have already looked into the fileapi.h function GetFileAttributesA() which gave me access to the file attribute constants like FILE_ATTRIBUTE_COMPRESSED, FILE_ATTRIBUTE_READONLY...
Even the GetFileAttributesExA() with GetFileExMaxInfoLevel was not able to return all the needed information.
if (FileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
std::cout << "File is compressed.";
}
if (FileAttributes & FILE_ATTRIBUTE_READONLY) {
std::cout << "File is a readonly file.";
}
I thought there should be a similar thing for file properties something like GetFilePropertiesExA().
But could not find any similar function so far.
Also I was able to get information like Date created, modified and size using WIN32_FIND_DATA.
Here is some sample code from Microsoft for reading/writing file properties. It's using the WinAPI to read the file properties.
You can find a list of available properties here.
Depending on what you want to do, you may also take a look at these PROPVARIANT functions. For example, when you want to store the value of a property into a string.

how to create a JSON file with c++ methods

We are doing a black box testing in our project,For that we wanted to use json and c++ and Jzon for parsing.can anybody show how to write a json file for c++ method and parse to get the node by using jzon ?
To write Json object (Jzon::Node) to file you can use Jzon::Writer class.
There are three methods writeStream,writeString and writeFile. Based on target where you want to save your object you can you appropriate method. To save into file you should use writeFile.
You code should be like this.
std::string filename="some path and file name.json";
Jzon::Node node;
//fill your object
Jzon::Writer write;
write.writeFile(node,filename);

How to call sink->imbue when using boost::log::init_from_settings?

How to call sink->imbue for text file sink when using init_from_settings?
I checked the source code and didn't find a way to re-access those sinks.
Seems that register_sink_factory is the extension, but the default factories are all in init_from_settings.cpp, so I'm not able to use an a decorator pattern to implement it easily.
I tried was set global locale, but it breaks RotationSize param (which doesn't accept int with decimal point)
Another way is:
auto previousLocale = std::locale::global(boost::locale::generator()("zh_CN.UTF-8"));
logging::init_from_settings(settings);
logging::add_common_attributes();
std::locale::global(previousLocale);
Any better ideas?
You can register a sink factory that will configure the sink the way you need. You can find an example here.

Create registry entry to associate file extension with application in C++

I would like to know the cleanest way of registering a file extension with my C++ application so that when a data file associated with my program is double clicked, the application is opened and the filename is passed as a parameter to the application.
Currently, I do this through my wix installer, but there are some instances where the application will not be installed on ths user's computer, so I also need the option of creating the registry key through the application.
Additionally, will this also mean that if the application is removed, unused entries in the registry will be left lying around?
Your basic overview of the process is found in this MSDN article. The key parts are at the bottom of the list:
Register the ProgID
A ProgID (essentially, the file type registry key) is what contains your important file type properties, such as icon, description, and context menu items including applications used when the file is double clicked. Many extensions may have the same file type. That mapping is done in the next step:
Register the file name extension for the file type
Here, you set a registry value for your extension, setting that extension's file type to the ProgID you created in the previous step.
The minimum amount of work required to get a file to open with your application is setting/creating two registry keys. In this example .reg file, I create a file type (blergcorp.blergapp.v1) and associate a file extension (.blerg) with it.
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command]
#="c:\path\to\app.exe \"%1\""
[HKEY_CURRENT_USER\Software\Classes\.blerg]
#="blergcorp.blergapp.v1"
Now, you probably want to accomplish this programmatically. To be absolutely kosher, you could check for the existence of these keys, and change your program behavior accordingly, especially if you're assuming control of some common file extension. However, the goal can be accomplished by setting those two keys using the SetValue function.
I'm not positive of the exact C++ syntax, but in C# the syntax looks something like this:
Registry.SetValue(#"HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command", null, #"c:\path\to\app.exe \"%1\"");
Registry.SetValue(#"HKEY_CURRENT_USER\Software\Classes\.blerg", null, "blergcorp.blergapp.v1");
Of course you could manually open each sub key, manually create the ProgID and extension subkey, and then set the key value, but a nice thing about the SetValue function is that if the keys or values don't exist, they will automatically be created. Very handy.
Now, a quick word about which hive to use. Many file association examples online, including ones on MSDN, show these keys being set in HKEY_CLASSES_ROOT. I don't recommend doing this. That hive is a merged, virtual view of HKEY_LOCAL_MACHINE\Software\Classes (the system defaults) and HKEY_CURRENT_USER\Software\Classes (the per-user settings), and writes to any subkey in the hive are redirected to the same key in HKEY_LOCAL_MACHINE\Software\Classes. Now, there's no direct problem doing this, but you may run into this issue: If you write to HKCR (redirected to HKLM), and the user has specified the same keys with different values in HKCU, the HKCU values will take precedence. Therefore, your writes will succeed but you won't see any change, because HKEY_CURRENT_USER settings take precedence over HKEY_LOCAL_MACHINE settings.
Therefore, you should take this into consideration when designing your application. Now, on the flip side, you can write to only HKEY_CURRENT_USER, as my examples here show. However, that file association setting will only be loaded for the current user, and if your application has been installed for all users, your application won't launch when that other user opens the file in Windows.
That should be a decent primer for what you want to do. For further reading I suggest
Best Practices for File Association
File Types and File Association, especially
How File Associations Work
And see also my similar answer to a similar question:
Associating file extensions with a program
This is a two step process:
1. Define a program that would take care of extension: (unless you want to use existing one)
1.1 create a key in "HKCU\\Software\\Classes\\" for example
"Software\\Classes\\YourProgramName.file.ext"
1.2 create subkey "Software\\Classes\\YourProgramName.file.ext\\DefaultIcon"
1.2.1 set default value ("") to your application full path to get
icon from resources
1.3 create a subkey "Software\\Classes\\YourProgramName.file.ext\\Shell\\OperationName\\Command"
OperationName = for example Open, Print or Other
1.3.1 set default value ("") to your application full path +optional runtime params (filename)
2.Associate file extension with program.
2.1 create a key HKCU\\Software\\Classes\\.ext - here goes your extension
2.2 set default value to the program definition key
("YourProgramName.file.ext")
Below is part of the program written in c# which associate file extension. It is not c++ but i think it is simple enought to explain itself and AFAIK it is verv simmilar if not identical to the code in c++
1.
RegistryKey keyPFCTExt0 = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc", true);
if (keyPFCTExt0 == null)
{
keyPFCTExt0 = Registry.CurrentUser.CreateSubKey("Software\\Classes\\PFCT.file.enc");
keyPFCTExt0.CreateSubKey("DefaultIcon");
RegistryKey keyPFCTExt0ext = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc\\DefaultIcon", true);
keyPFCTExt0ext.SetValue("", Application.ExecutablePath +",0");
keyPFCTExt0ext.Close();
keyPFCTExt0.CreateSubKey("Shell\\PFCT_Decrypt\\Command");
}
keyPFCTExt0.SetValue("", "PFCT.file.enc");
keyPFCTExt0.Close();
2.
RegistryKey keyPFCTExt1 = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc\\Shell\\PFCT_Decrypt\\Command", true);
if (keyPFCTExt1 == null)
keyPFCTExt1 = Registry.CurrentUser.CreateSubKey("Software\\Classes\\PFCT.file.enc\\Shell\\PFCT_Decrypt\\Command");
keyPFCTExt1.SetValue("", Application.ExecutablePath + " !d %1"); //!d %1 are optional params, here !d string and full file path
keyPFCTExt1.Close();
I don't know why people keep saying that HKEY_CURRENT_USER\Software\Classes\<.ext>'s Default value (which will redirect you into another (software-created) class.
It does work, but it will be overridden by
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<.ext>\UserChoice
And I believe Microsoft recommends the second practice- because it's what the built-in "open with" is doing. The value of Progid" key is equal to default value of HKEY_CURRENT_USER\Software\Classes\<.ext> in this case.
I found the following while trying to manipulate associations using C#:
hkcu\software\microsoft\windows\currentVersion\explorer\fileexts.reg\userchoice -> for user specific settings. The values in the openWithProgIds
key point to the keys in the hkcr.
hkcr\xfile\shell\open\muiVerb value or hkcr\xfile\shell\open\command\default value -> affects open handler. This is the value that contains the path to a program.
hkcr\ .x -> affects context menu (new x) among other things related to the menus.
I don't know the C++ code, but given these info you must be able to manipulate the registry using the registry API.